Skip to content

Commit 00490c2

Browse files
mlankhorstjnikula
authored andcommitted
drm/i915: Consider SPLL as another shared pll, v2.
When diagnosing a unrelated bug for someone on irc, it would seem the hardware can be brought up by the BIOS with the embedded displayport using the SPLL for spread spectrum. Right now this is not handled well in i915, and it calculates the crtc needs to be reprogrammed on the first modeset without SSC, but the SPLL itself was kept active. Fix this by exposing SPLL as a shared pll that will not be returned by intel_get_shared_dpll; you have to know it exists to use it. Changes since v1: - Create a separate dpll_hw_state.spll for spll, and use separate pll functions for spll. Tested-by: Emil Renner Berthing <[email protected]> Tested-by: Gabriel Feceoru <[email protected]> Reviewed-by: Daniel Vetter <[email protected]> Signed-off-by: Maarten Lankhorst <[email protected]> Link: http://patchwork.freedesktop.org/patch/msgid/1447681332-6318-1-git-send-email-maarten.lankhorst@linux.intel.com Signed-off-by: Jani Nikula <[email protected]>
1 parent 0f94592 commit 00490c2

File tree

4 files changed

+83
-41
lines changed

4 files changed

+83
-41
lines changed

drivers/gpu/drm/i915/i915_drv.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,8 @@ enum intel_dpll_id {
351351
/* hsw/bdw */
352352
DPLL_ID_WRPLL1 = 0,
353353
DPLL_ID_WRPLL2 = 1,
354+
DPLL_ID_SPLL = 2,
355+
354356
/* skl */
355357
DPLL_ID_SKL_DPLL1 = 0,
356358
DPLL_ID_SKL_DPLL2 = 1,
@@ -367,6 +369,7 @@ struct intel_dpll_hw_state {
367369

368370
/* hsw, bdw */
369371
uint32_t wrpll;
372+
uint32_t spll;
370373

371374
/* skl */
372375
/*

drivers/gpu/drm/i915/intel_crt.c

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -138,18 +138,6 @@ static void hsw_crt_get_config(struct intel_encoder *encoder,
138138
pipe_config->base.adjusted_mode.flags |= intel_crt_get_flags(encoder);
139139
}
140140

141-
static void hsw_crt_pre_enable(struct intel_encoder *encoder)
142-
{
143-
struct drm_device *dev = encoder->base.dev;
144-
struct drm_i915_private *dev_priv = dev->dev_private;
145-
146-
WARN(I915_READ(SPLL_CTL) & SPLL_PLL_ENABLE, "SPLL already enabled\n");
147-
I915_WRITE(SPLL_CTL,
148-
SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC);
149-
POSTING_READ(SPLL_CTL);
150-
udelay(20);
151-
}
152-
153141
/* Note: The caller is required to filter out dpms modes not supported by the
154142
* platform. */
155143
static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode)
@@ -216,19 +204,6 @@ static void pch_post_disable_crt(struct intel_encoder *encoder)
216204
intel_disable_crt(encoder);
217205
}
218206

219-
static void hsw_crt_post_disable(struct intel_encoder *encoder)
220-
{
221-
struct drm_device *dev = encoder->base.dev;
222-
struct drm_i915_private *dev_priv = dev->dev_private;
223-
uint32_t val;
224-
225-
DRM_DEBUG_KMS("Disabling SPLL\n");
226-
val = I915_READ(SPLL_CTL);
227-
WARN_ON(!(val & SPLL_PLL_ENABLE));
228-
I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE);
229-
POSTING_READ(SPLL_CTL);
230-
}
231-
232207
static void intel_enable_crt(struct intel_encoder *encoder)
233208
{
234209
struct intel_crt *crt = intel_encoder_to_crt(encoder);
@@ -280,6 +255,10 @@ static bool intel_crt_compute_config(struct intel_encoder *encoder,
280255
if (HAS_DDI(dev)) {
281256
pipe_config->ddi_pll_sel = PORT_CLK_SEL_SPLL;
282257
pipe_config->port_clock = 135000 * 2;
258+
259+
pipe_config->dpll_hw_state.wrpll = 0;
260+
pipe_config->dpll_hw_state.spll =
261+
SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC;
283262
}
284263

285264
return true;
@@ -860,8 +839,6 @@ void intel_crt_init(struct drm_device *dev)
860839
if (HAS_DDI(dev)) {
861840
crt->base.get_config = hsw_crt_get_config;
862841
crt->base.get_hw_state = intel_ddi_get_hw_state;
863-
crt->base.pre_enable = hsw_crt_pre_enable;
864-
crt->base.post_disable = hsw_crt_post_disable;
865842
} else {
866843
crt->base.get_config = intel_crt_get_config;
867844
crt->base.get_hw_state = intel_crt_get_hw_state;

drivers/gpu/drm/i915/intel_ddi.c

Lines changed: 65 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1286,6 +1286,18 @@ hsw_ddi_pll_select(struct intel_crtc *intel_crtc,
12861286
}
12871287

12881288
crtc_state->ddi_pll_sel = PORT_CLK_SEL_WRPLL(pll->id);
1289+
} else if (crtc_state->ddi_pll_sel == PORT_CLK_SEL_SPLL) {
1290+
struct drm_atomic_state *state = crtc_state->base.state;
1291+
struct intel_shared_dpll_config *spll =
1292+
&intel_atomic_get_shared_dpll_state(state)[DPLL_ID_SPLL];
1293+
1294+
if (spll->crtc_mask &&
1295+
WARN_ON(spll->hw_state.spll != crtc_state->dpll_hw_state.spll))
1296+
return false;
1297+
1298+
crtc_state->shared_dpll = DPLL_ID_SPLL;
1299+
spll->hw_state.spll = crtc_state->dpll_hw_state.spll;
1300+
spll->crtc_mask |= 1 << intel_crtc->pipe;
12891301
}
12901302

12911303
return true;
@@ -2437,16 +2449,24 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder)
24372449
}
24382450
}
24392451

2440-
static void hsw_ddi_pll_enable(struct drm_i915_private *dev_priv,
2452+
static void hsw_ddi_wrpll_enable(struct drm_i915_private *dev_priv,
24412453
struct intel_shared_dpll *pll)
24422454
{
24432455
I915_WRITE(WRPLL_CTL(pll->id), pll->config.hw_state.wrpll);
24442456
POSTING_READ(WRPLL_CTL(pll->id));
24452457
udelay(20);
24462458
}
24472459

2448-
static void hsw_ddi_pll_disable(struct drm_i915_private *dev_priv,
2460+
static void hsw_ddi_spll_enable(struct drm_i915_private *dev_priv,
24492461
struct intel_shared_dpll *pll)
2462+
{
2463+
I915_WRITE(SPLL_CTL, pll->config.hw_state.spll);
2464+
POSTING_READ(SPLL_CTL);
2465+
udelay(20);
2466+
}
2467+
2468+
static void hsw_ddi_wrpll_disable(struct drm_i915_private *dev_priv,
2469+
struct intel_shared_dpll *pll)
24502470
{
24512471
uint32_t val;
24522472

@@ -2455,9 +2475,19 @@ static void hsw_ddi_pll_disable(struct drm_i915_private *dev_priv,
24552475
POSTING_READ(WRPLL_CTL(pll->id));
24562476
}
24572477

2458-
static bool hsw_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
2459-
struct intel_shared_dpll *pll,
2460-
struct intel_dpll_hw_state *hw_state)
2478+
static void hsw_ddi_spll_disable(struct drm_i915_private *dev_priv,
2479+
struct intel_shared_dpll *pll)
2480+
{
2481+
uint32_t val;
2482+
2483+
val = I915_READ(SPLL_CTL);
2484+
I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE);
2485+
POSTING_READ(SPLL_CTL);
2486+
}
2487+
2488+
static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv,
2489+
struct intel_shared_dpll *pll,
2490+
struct intel_dpll_hw_state *hw_state)
24612491
{
24622492
uint32_t val;
24632493

@@ -2470,25 +2500,50 @@ static bool hsw_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
24702500
return val & WRPLL_PLL_ENABLE;
24712501
}
24722502

2503+
static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv,
2504+
struct intel_shared_dpll *pll,
2505+
struct intel_dpll_hw_state *hw_state)
2506+
{
2507+
uint32_t val;
2508+
2509+
if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS))
2510+
return false;
2511+
2512+
val = I915_READ(SPLL_CTL);
2513+
hw_state->spll = val;
2514+
2515+
return val & SPLL_PLL_ENABLE;
2516+
}
2517+
2518+
24732519
static const char * const hsw_ddi_pll_names[] = {
24742520
"WRPLL 1",
24752521
"WRPLL 2",
2522+
"SPLL"
24762523
};
24772524

24782525
static void hsw_shared_dplls_init(struct drm_i915_private *dev_priv)
24792526
{
24802527
int i;
24812528

2482-
dev_priv->num_shared_dpll = 2;
2529+
dev_priv->num_shared_dpll = 3;
24832530

2484-
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
2531+
for (i = 0; i < 2; i++) {
24852532
dev_priv->shared_dplls[i].id = i;
24862533
dev_priv->shared_dplls[i].name = hsw_ddi_pll_names[i];
2487-
dev_priv->shared_dplls[i].disable = hsw_ddi_pll_disable;
2488-
dev_priv->shared_dplls[i].enable = hsw_ddi_pll_enable;
2534+
dev_priv->shared_dplls[i].disable = hsw_ddi_wrpll_disable;
2535+
dev_priv->shared_dplls[i].enable = hsw_ddi_wrpll_enable;
24892536
dev_priv->shared_dplls[i].get_hw_state =
2490-
hsw_ddi_pll_get_hw_state;
2537+
hsw_ddi_wrpll_get_hw_state;
24912538
}
2539+
2540+
/* SPLL is special, but needs to be initialized anyway.. */
2541+
dev_priv->shared_dplls[i].id = i;
2542+
dev_priv->shared_dplls[i].name = hsw_ddi_pll_names[i];
2543+
dev_priv->shared_dplls[i].disable = hsw_ddi_spll_disable;
2544+
dev_priv->shared_dplls[i].enable = hsw_ddi_spll_enable;
2545+
dev_priv->shared_dplls[i].get_hw_state = hsw_ddi_spll_get_hw_state;
2546+
24922547
}
24932548

24942549
static const char * const skl_ddi_pll_names[] = {

drivers/gpu/drm/i915/intel_display.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4239,6 +4239,7 @@ struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc,
42394239
struct intel_shared_dpll *pll;
42404240
struct intel_shared_dpll_config *shared_dpll;
42414241
enum intel_dpll_id i;
4242+
int max = dev_priv->num_shared_dpll;
42424243

42434244
shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state);
42444245

@@ -4273,9 +4274,11 @@ struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc,
42734274
WARN_ON(shared_dpll[i].crtc_mask);
42744275

42754276
goto found;
4276-
}
4277+
} else if (INTEL_INFO(dev_priv)->gen < 9 && HAS_DDI(dev_priv))
4278+
/* Do not consider SPLL */
4279+
max = 2;
42774280

4278-
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
4281+
for (i = 0; i < max; i++) {
42794282
pll = &dev_priv->shared_dplls[i];
42804283

42814284
/* Only want to check enabled timings first */
@@ -9725,6 +9728,8 @@ static void haswell_get_ddi_pll(struct drm_i915_private *dev_priv,
97259728
case PORT_CLK_SEL_WRPLL2:
97269729
pipe_config->shared_dpll = DPLL_ID_WRPLL2;
97279730
break;
9731+
case PORT_CLK_SEL_SPLL:
9732+
pipe_config->shared_dpll = DPLL_ID_SPLL;
97289733
}
97299734
}
97309735

@@ -12005,9 +12010,10 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
1200512010
pipe_config->dpll_hw_state.cfgcr1,
1200612011
pipe_config->dpll_hw_state.cfgcr2);
1200712012
} else if (HAS_DDI(dev)) {
12008-
DRM_DEBUG_KMS("ddi_pll_sel: %u; dpll_hw_state: wrpll: 0x%x\n",
12013+
DRM_DEBUG_KMS("ddi_pll_sel: %u; dpll_hw_state: wrpll: 0x%x spll: 0x%x\n",
1200912014
pipe_config->ddi_pll_sel,
12010-
pipe_config->dpll_hw_state.wrpll);
12015+
pipe_config->dpll_hw_state.wrpll,
12016+
pipe_config->dpll_hw_state.spll);
1201112017
} else {
1201212018
DRM_DEBUG_KMS("dpll_hw_state: dpll: 0x%x, dpll_md: 0x%x, "
1201312019
"fp0: 0x%x, fp1: 0x%x\n",
@@ -12530,6 +12536,7 @@ intel_pipe_config_compare(struct drm_device *dev,
1253012536
PIPE_CONF_CHECK_X(dpll_hw_state.fp0);
1253112537
PIPE_CONF_CHECK_X(dpll_hw_state.fp1);
1253212538
PIPE_CONF_CHECK_X(dpll_hw_state.wrpll);
12539+
PIPE_CONF_CHECK_X(dpll_hw_state.spll);
1253312540
PIPE_CONF_CHECK_X(dpll_hw_state.ctrl1);
1253412541
PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr1);
1253512542
PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr2);

0 commit comments

Comments
 (0)