Skip to content

Commit a927c92

Browse files
committed
drm/i915/cnl: Initialize PLLs
Although CNL follows PLL initialization more like Skylake than Broxton we have a completely different initialization sequence and registers used. One big difference from SKL is that CDCLK PLL is now exclusive (ADPLL) and for DDIs and MIPI we need to use DFGPLLs 0, 1 or 2. v2: Accept all Ander's suggestions and fixes: - Registers and bits names prefix - Group pll functions - bits masks fixes - remove read and modify on cfgcr1 - fix cfgcr0 setup v3: Set SSC_ENABLE for DP. Fix HDMI_MODE cfgcr0. Avoid touch cfgcr0 on DP. Add missed else on dpll_mgr definition so we use cnl one, not hsw. v3: Centra freq should be always set to default and change bits definitions to (1 << 1) instead of (1<<1). (by Paulo) v4: Rebased. Cc: Paulo Zanoni <[email protected]> Cc: Ville Syrjälä <[email protected]> Cc: Kahola, Mika <[email protected]> Reviewed-by: Ander Conselvan De Oliveira <[email protected]> Signed-off-by: Rodrigo Vivi <[email protected]> Link: http://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 8b0f7e0 commit a927c92

File tree

3 files changed

+350
-2
lines changed

3 files changed

+350
-2
lines changed

drivers/gpu/drm/i915/i915_reg.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
6060
#define _MMIO_PORT(port, a, b) _MMIO(_PORT(port, a, b))
6161
#define _MMIO_PIPE3(pipe, a, b, c) _MMIO(_PICK(pipe, a, b, c))
6262
#define _MMIO_PORT3(pipe, a, b, c) _MMIO(_PICK(pipe, a, b, c))
63+
#define _PLL(pll, a, b) ((a) + (pll)*((b)-(a)))
64+
#define _MMIO_PLL(pll, a, b) _MMIO(_PLL(pll, a, b))
6365
#define _PHY3(phy, ...) _PICK(phy, __VA_ARGS__)
6466
#define _MMIO_PHY3(phy, a, b, c) _MMIO(_PHY3(phy, a, b, c))
6567

@@ -8143,6 +8145,52 @@ enum {
81438145
#define DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(port) ((port)*2)
81448146
#define DPCLKA_CFGCR0_DDI_CLK_SEL(pll, port) ((pll) << ((port)*2))
81458147

8148+
/* CNL PLL */
8149+
#define DPLL0_ENABLE 0x46010
8150+
#define DPLL1_ENABLE 0x46014
8151+
#define PLL_ENABLE (1 << 31)
8152+
#define PLL_LOCK (1 << 30)
8153+
#define PLL_POWER_ENABLE (1 << 27)
8154+
#define PLL_POWER_STATE (1 << 26)
8155+
#define CNL_DPLL_ENABLE(pll) _MMIO_PLL(pll, DPLL0_ENABLE, DPLL1_ENABLE)
8156+
8157+
#define _CNL_DPLL0_CFGCR0 0x6C000
8158+
#define _CNL_DPLL1_CFGCR0 0x6C080
8159+
#define DPLL_CFGCR0_HDMI_MODE (1 << 30)
8160+
#define DPLL_CFGCR0_SSC_ENABLE (1 << 29)
8161+
#define DPLL_CFGCR0_LINK_RATE_MASK (0xf << 25)
8162+
#define DPLL_CFGCR0_LINK_RATE_2700 (0 << 25)
8163+
#define DPLL_CFGCR0_LINK_RATE_1350 (1 << 25)
8164+
#define DPLL_CFGCR0_LINK_RATE_810 (2 << 25)
8165+
#define DPLL_CFGCR0_LINK_RATE_1620 (3 << 25)
8166+
#define DPLL_CFGCR0_LINK_RATE_1080 (4 << 25)
8167+
#define DPLL_CFGCR0_LINK_RATE_2160 (5 << 25)
8168+
#define DPLL_CFGCR0_LINK_RATE_3240 (6 << 25)
8169+
#define DPLL_CFGCR0_LINK_RATE_4050 (7 << 25)
8170+
#define DPLL_CFGCR0_DCO_FRACTION_MASK (0x7fff << 10)
8171+
#define DPLL_CFGCR0_DCO_FRACTION(x) ((x) << 10)
8172+
#define DPLL_CFGCR0_DCO_INTEGER_MASK (0x3ff)
8173+
#define CNL_DPLL_CFGCR0(pll) _MMIO_PLL(pll, _CNL_DPLL0_CFGCR0, _CNL_DPLL1_CFGCR0)
8174+
8175+
#define _CNL_DPLL0_CFGCR1 0x6C004
8176+
#define _CNL_DPLL1_CFGCR1 0x6C084
8177+
#define DPLL_CFGCR1_QDIV_RATIO_MASK (0xff << 10)
8178+
#define DPLL_CFGCR1_QDIV_RATIO(x) ((x) << 10)
8179+
#define DPLL_CFGCR1_QDIV_MODE(x) ((x) << 9)
8180+
#define DPLL_CFGCR1_KDIV_MASK (7 << 6)
8181+
#define DPLL_CFGCR1_KDIV(x) ((x) << 6)
8182+
#define DPLL_CFGCR1_KDIV_1 (1 << 6)
8183+
#define DPLL_CFGCR1_KDIV_2 (2 << 6)
8184+
#define DPLL_CFGCR1_KDIV_4 (4 << 6)
8185+
#define DPLL_CFGCR1_PDIV_MASK (0xf << 2)
8186+
#define DPLL_CFGCR1_PDIV(x) ((x) << 2)
8187+
#define DPLL_CFGCR1_PDIV_2 (1 << 2)
8188+
#define DPLL_CFGCR1_PDIV_3 (2 << 2)
8189+
#define DPLL_CFGCR1_PDIV_5 (4 << 2)
8190+
#define DPLL_CFGCR1_PDIV_7 (8 << 2)
8191+
#define DPLL_CFGCR1_CENTRAL_FREQ (3 << 0)
8192+
#define CNL_DPLL_CFGCR1(pll) _MMIO_PLL(pll, _CNL_DPLL0_CFGCR1, _CNL_DPLL1_CFGCR1)
8193+
81468194
/* BXT display engine PLL */
81478195
#define BXT_DE_PLL_CTL _MMIO(0x6d000)
81488196
#define BXT_DE_PLL_RATIO(x) (x) /* {60,65,100} * 19.2MHz */

drivers/gpu/drm/i915/intel_dpll_mgr.c

Lines changed: 298 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1321,7 +1321,6 @@ static bool skl_ddi_hdmi_pll_dividers(struct intel_crtc *crtc,
13211321
return true;
13221322
}
13231323

1324-
13251324
static bool
13261325
skl_ddi_dp_set_dpll_hw_state(int clock,
13271326
struct intel_dpll_hw_state *dpll_hw_state)
@@ -1967,6 +1966,301 @@ static const struct intel_dpll_mgr bxt_pll_mgr = {
19671966
.dump_hw_state = bxt_dump_hw_state,
19681967
};
19691968

1969+
static void cnl_ddi_pll_enable(struct drm_i915_private *dev_priv,
1970+
struct intel_shared_dpll *pll)
1971+
{
1972+
uint32_t val;
1973+
1974+
/* 1. Enable DPLL power in DPLL_ENABLE. */
1975+
val = I915_READ(CNL_DPLL_ENABLE(pll->id));
1976+
val |= PLL_POWER_ENABLE;
1977+
I915_WRITE(CNL_DPLL_ENABLE(pll->id), val);
1978+
1979+
/* 2. Wait for DPLL power state enabled in DPLL_ENABLE. */
1980+
if (intel_wait_for_register(dev_priv,
1981+
CNL_DPLL_ENABLE(pll->id),
1982+
PLL_POWER_STATE,
1983+
PLL_POWER_STATE,
1984+
5))
1985+
DRM_ERROR("PLL %d Power not enabled\n", pll->id);
1986+
1987+
/*
1988+
* 3. Configure DPLL_CFGCR0 to set SSC enable/disable,
1989+
* select DP mode, and set DP link rate.
1990+
*/
1991+
val = pll->state.hw_state.cfgcr0;
1992+
I915_WRITE(CNL_DPLL_CFGCR0(pll->id), val);
1993+
1994+
/* 4. Reab back to ensure writes completed */
1995+
POSTING_READ(CNL_DPLL_CFGCR0(pll->id));
1996+
1997+
/* 3. Configure DPLL_CFGCR0 */
1998+
/* Avoid touch CFGCR1 if HDMI mode is not enabled */
1999+
if (pll->state.hw_state.cfgcr0 & DPLL_CTRL1_HDMI_MODE(pll->id)) {
2000+
val = pll->state.hw_state.cfgcr1;
2001+
I915_WRITE(CNL_DPLL_CFGCR1(pll->id), val);
2002+
/* 4. Reab back to ensure writes completed */
2003+
POSTING_READ(CNL_DPLL_CFGCR1(pll->id));
2004+
}
2005+
2006+
/*
2007+
* 5. If the frequency will result in a change to the voltage
2008+
* requirement, follow the Display Voltage Frequency Switching
2009+
* Sequence Before Frequency Change
2010+
*
2011+
* FIXME: (DVFS) is used to adjust the display voltage to match the
2012+
* display clock frequencies
2013+
*/
2014+
2015+
/* 6. Enable DPLL in DPLL_ENABLE. */
2016+
val = I915_READ(CNL_DPLL_ENABLE(pll->id));
2017+
val |= PLL_ENABLE;
2018+
I915_WRITE(CNL_DPLL_ENABLE(pll->id), val);
2019+
2020+
/* 7. Wait for PLL lock status in DPLL_ENABLE. */
2021+
if (intel_wait_for_register(dev_priv,
2022+
CNL_DPLL_ENABLE(pll->id),
2023+
PLL_LOCK,
2024+
PLL_LOCK,
2025+
5))
2026+
DRM_ERROR("PLL %d not locked\n", pll->id);
2027+
2028+
/*
2029+
* 8. If the frequency will result in a change to the voltage
2030+
* requirement, follow the Display Voltage Frequency Switching
2031+
* Sequence After Frequency Change
2032+
*
2033+
* FIXME: (DVFS) is used to adjust the display voltage to match the
2034+
* display clock frequencies
2035+
*/
2036+
2037+
/*
2038+
* 9. turn on the clock for the DDI and map the DPLL to the DDI
2039+
* Done at intel_ddi_clk_select
2040+
*/
2041+
}
2042+
2043+
static void cnl_ddi_pll_disable(struct drm_i915_private *dev_priv,
2044+
struct intel_shared_dpll *pll)
2045+
{
2046+
uint32_t val;
2047+
2048+
/*
2049+
* 1. Configure DPCLKA_CFGCR0 to turn off the clock for the DDI.
2050+
* Done at intel_ddi_post_disable
2051+
*/
2052+
2053+
/*
2054+
* 2. If the frequency will result in a change to the voltage
2055+
* requirement, follow the Display Voltage Frequency Switching
2056+
* Sequence Before Frequency Change
2057+
*
2058+
* FIXME: (DVFS) is used to adjust the display voltage to match the
2059+
* display clock frequencies
2060+
*/
2061+
2062+
/* 3. Disable DPLL through DPLL_ENABLE. */
2063+
val = I915_READ(CNL_DPLL_ENABLE(pll->id));
2064+
val &= ~PLL_ENABLE;
2065+
I915_WRITE(CNL_DPLL_ENABLE(pll->id), val);
2066+
2067+
/* 4. Wait for PLL not locked status in DPLL_ENABLE. */
2068+
if (intel_wait_for_register(dev_priv,
2069+
CNL_DPLL_ENABLE(pll->id),
2070+
PLL_LOCK,
2071+
0,
2072+
5))
2073+
DRM_ERROR("PLL %d locked\n", pll->id);
2074+
2075+
/*
2076+
* 5. If the frequency will result in a change to the voltage
2077+
* requirement, follow the Display Voltage Frequency Switching
2078+
* Sequence After Frequency Change
2079+
*
2080+
* FIXME: (DVFS) is used to adjust the display voltage to match the
2081+
* display clock frequencies
2082+
*/
2083+
2084+
/* 6. Disable DPLL power in DPLL_ENABLE. */
2085+
val = I915_READ(CNL_DPLL_ENABLE(pll->id));
2086+
val &= ~PLL_POWER_ENABLE;
2087+
I915_WRITE(CNL_DPLL_ENABLE(pll->id), val);
2088+
2089+
/* 7. Wait for DPLL power state disabled in DPLL_ENABLE. */
2090+
if (intel_wait_for_register(dev_priv,
2091+
CNL_DPLL_ENABLE(pll->id),
2092+
PLL_POWER_STATE,
2093+
0,
2094+
5))
2095+
DRM_ERROR("PLL %d Power not disabled\n", pll->id);
2096+
}
2097+
2098+
static bool cnl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
2099+
struct intel_shared_dpll *pll,
2100+
struct intel_dpll_hw_state *hw_state)
2101+
{
2102+
uint32_t val;
2103+
bool ret;
2104+
2105+
if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
2106+
return false;
2107+
2108+
ret = false;
2109+
2110+
val = I915_READ(CNL_DPLL_ENABLE(pll->id));
2111+
if (!(val & PLL_ENABLE))
2112+
goto out;
2113+
2114+
val = I915_READ(CNL_DPLL_CFGCR0(pll->id));
2115+
hw_state->cfgcr0 = val;
2116+
2117+
/* avoid reading back stale values if HDMI mode is not enabled */
2118+
if (val & DPLL_CFGCR0_HDMI_MODE) {
2119+
hw_state->cfgcr1 = I915_READ(CNL_DPLL_CFGCR1(pll->id));
2120+
}
2121+
ret = true;
2122+
2123+
out:
2124+
intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
2125+
2126+
return ret;
2127+
}
2128+
2129+
static bool cnl_ddi_hdmi_pll_dividers(struct intel_crtc *crtc,
2130+
struct intel_crtc_state *crtc_state,
2131+
int clock)
2132+
{
2133+
uint32_t cfgcr0, cfgcr1;
2134+
struct skl_wrpll_params wrpll_params = { 0, };
2135+
2136+
cfgcr0 = DPLL_CFGCR0_HDMI_MODE;
2137+
2138+
/* FIXME: Proper wrpll calculation done in a following patch */
2139+
return false;
2140+
2141+
cfgcr0 |= DPLL_CFGCR0_DCO_FRACTION(wrpll_params.dco_fraction) |
2142+
wrpll_params.dco_integer;
2143+
2144+
cfgcr1 = DPLL_CFGCR1_QDIV_RATIO(wrpll_params.qdiv_ratio) |
2145+
DPLL_CFGCR1_QDIV_MODE(wrpll_params.qdiv_mode) |
2146+
DPLL_CFGCR1_KDIV(wrpll_params.kdiv) |
2147+
DPLL_CFGCR1_PDIV(wrpll_params.pdiv) |
2148+
wrpll_params.central_freq |
2149+
DPLL_CFGCR1_CENTRAL_FREQ;
2150+
2151+
memset(&crtc_state->dpll_hw_state, 0,
2152+
sizeof(crtc_state->dpll_hw_state));
2153+
2154+
crtc_state->dpll_hw_state.cfgcr0 = cfgcr0;
2155+
crtc_state->dpll_hw_state.cfgcr1 = cfgcr1;
2156+
return true;
2157+
}
2158+
2159+
bool cnl_ddi_dp_set_dpll_hw_state(int clock,
2160+
struct intel_dpll_hw_state *dpll_hw_state)
2161+
{
2162+
uint32_t cfgcr0;
2163+
2164+
cfgcr0 = DPLL_CFGCR0_SSC_ENABLE;
2165+
2166+
switch (clock / 2) {
2167+
case 81000:
2168+
cfgcr0 |= DPLL_CFGCR0_LINK_RATE_810;
2169+
break;
2170+
case 135000:
2171+
cfgcr0 |= DPLL_CFGCR0_LINK_RATE_1350;
2172+
break;
2173+
case 270000:
2174+
cfgcr0 |= DPLL_CFGCR0_LINK_RATE_2700;
2175+
break;
2176+
/* eDP 1.4 rates */
2177+
case 162000:
2178+
cfgcr0 |= DPLL_CFGCR0_LINK_RATE_1620;
2179+
break;
2180+
case 108000:
2181+
cfgcr0 |= DPLL_CFGCR0_LINK_RATE_1080;
2182+
break;
2183+
case 216000:
2184+
cfgcr0 |= DPLL_CFGCR0_LINK_RATE_2160;
2185+
break;
2186+
case 324000:
2187+
/* Some SKUs may require elevated I/O voltage to support this */
2188+
cfgcr0 |= DPLL_CFGCR0_LINK_RATE_3240;
2189+
break;
2190+
case 405000:
2191+
/* Some SKUs may require elevated I/O voltage to support this */
2192+
cfgcr0 |= DPLL_CFGCR0_LINK_RATE_4050;
2193+
break;
2194+
}
2195+
2196+
dpll_hw_state->cfgcr0 = cfgcr0;
2197+
return true;
2198+
}
2199+
2200+
static struct intel_shared_dpll *
2201+
cnl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
2202+
struct intel_encoder *encoder)
2203+
{
2204+
struct intel_shared_dpll *pll;
2205+
int clock = crtc_state->port_clock;
2206+
bool bret;
2207+
struct intel_dpll_hw_state dpll_hw_state;
2208+
2209+
memset(&dpll_hw_state, 0, sizeof(dpll_hw_state));
2210+
2211+
if (encoder->type == INTEL_OUTPUT_HDMI) {
2212+
bret = cnl_ddi_hdmi_pll_dividers(crtc, crtc_state, clock);
2213+
if (!bret) {
2214+
DRM_DEBUG_KMS("Could not get HDMI pll dividers.\n");
2215+
return NULL;
2216+
}
2217+
} else if (encoder->type == INTEL_OUTPUT_DP ||
2218+
encoder->type == INTEL_OUTPUT_DP_MST ||
2219+
encoder->type == INTEL_OUTPUT_EDP) {
2220+
bret = cnl_ddi_dp_set_dpll_hw_state(clock, &dpll_hw_state);
2221+
if (!bret) {
2222+
DRM_DEBUG_KMS("Could not set DP dpll HW state.\n");
2223+
return NULL;
2224+
}
2225+
crtc_state->dpll_hw_state = dpll_hw_state;
2226+
} else {
2227+
DRM_DEBUG_KMS("Skip DPLL setup for encoder %d\n",
2228+
encoder->type);
2229+
return NULL;
2230+
}
2231+
2232+
pll = intel_find_shared_dpll(crtc, crtc_state,
2233+
DPLL_ID_SKL_DPLL0,
2234+
DPLL_ID_SKL_DPLL2);
2235+
if (!pll) {
2236+
DRM_DEBUG_KMS("No PLL selected\n");
2237+
return NULL;
2238+
}
2239+
2240+
intel_reference_shared_dpll(pll, crtc_state);
2241+
2242+
return pll;
2243+
}
2244+
2245+
static const struct intel_shared_dpll_funcs cnl_ddi_pll_funcs = {
2246+
.enable = cnl_ddi_pll_enable,
2247+
.disable = cnl_ddi_pll_disable,
2248+
.get_hw_state = cnl_ddi_pll_get_hw_state,
2249+
};
2250+
2251+
static const struct dpll_info cnl_plls[] = {
2252+
{ "DPLL 0", DPLL_ID_SKL_DPLL0, &cnl_ddi_pll_funcs, 0 },
2253+
{ "DPLL 1", DPLL_ID_SKL_DPLL1, &cnl_ddi_pll_funcs, 0 },
2254+
{ "DPLL 2", DPLL_ID_SKL_DPLL2, &cnl_ddi_pll_funcs, 0 },
2255+
{ NULL, -1, NULL, },
2256+
};
2257+
2258+
static const struct intel_dpll_mgr cnl_pll_mgr = {
2259+
.dpll_info = cnl_plls,
2260+
.get_dpll = cnl_get_dpll,
2261+
.dump_hw_state = skl_dump_hw_state,
2262+
};
2263+
19702264
/**
19712265
* intel_shared_dpll_init - Initialize shared DPLLs
19722266
* @dev: drm device
@@ -1980,7 +2274,9 @@ void intel_shared_dpll_init(struct drm_device *dev)
19802274
const struct dpll_info *dpll_info;
19812275
int i;
19822276

1983-
if (IS_GEN9_BC(dev_priv))
2277+
if (IS_CANNONLAKE(dev_priv))
2278+
dpll_mgr = &cnl_pll_mgr;
2279+
else if (IS_GEN9_BC(dev_priv))
19842280
dpll_mgr = &skl_pll_mgr;
19852281
else if (IS_GEN9_LP(dev_priv))
19862282
dpll_mgr = &bxt_pll_mgr;

drivers/gpu/drm/i915/intel_dpll_mgr.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,10 @@ struct intel_dpll_hw_state {
128128
/* HDMI only, 0 when used for DP */
129129
uint32_t cfgcr1, cfgcr2;
130130

131+
/* cnl */
132+
uint32_t cfgcr0;
133+
/* CNL also uses cfgcr1 */
134+
131135
/* bxt */
132136
uint32_t ebb0, ebb4, pll0, pll1, pll2, pll3, pll6, pll8, pll9, pll10,
133137
pcsdw12;

0 commit comments

Comments
 (0)