Skip to content

Commit

Permalink
drm/i915: Make SKL/KBL DPLL0 managed by the shared dpll code
Browse files Browse the repository at this point in the history
Include DPLL0 in the managed dplls for SKL/KBL. While it has to be kept
enabled because of it driving CDCLK, it is better to special case that
inside the DPLL code than in the higher level.

v2: Use INTEL_DPLL_ALWAYS_ON flag. (Ander)

v3: Remove extremely paranoid WARN_ONs. (Maarten)
    Handle DPLL0 in skylake_get_ddi_pll() properly. (Ander)

Signed-off-by: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1457451987-17466-14-git-send-email-ander.conselvan.de.oliveira@intel.com
  • Loading branch information
Ander Conselvan de Oliveira committed Mar 9, 2016
1 parent 9d16da6 commit a3c988e
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 111 deletions.
21 changes: 0 additions & 21 deletions drivers/gpu/drm/i915/intel_ddi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1008,9 +1008,6 @@ skl_ddi_pll_select(struct intel_crtc *intel_crtc,
{
struct intel_shared_dpll *pll;

if (intel_encoder->type == INTEL_OUTPUT_EDP)
return true;

pll = intel_get_shared_dpll(intel_crtc, crtc_state, intel_encoder);
if (pll == NULL) {
DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
Expand Down Expand Up @@ -1570,24 +1567,6 @@ void intel_ddi_clk_select(struct intel_encoder *encoder,
uint32_t dpll = pipe_config->ddi_pll_sel;
uint32_t val;

/*
* DPLL0 is used for eDP and is the only "private" DPLL (as
* opposed to shared) on SKL
*/
if (encoder->type == INTEL_OUTPUT_EDP) {
WARN_ON(dpll != SKL_DPLL0);

val = I915_READ(DPLL_CTRL1);

val &= ~(DPLL_CTRL1_HDMI_MODE(dpll) |
DPLL_CTRL1_SSC(dpll) |
DPLL_CTRL1_LINK_RATE_MASK(dpll));
val |= pipe_config->dpll_hw_state.ctrl1 << (dpll * 6);

I915_WRITE(DPLL_CTRL1, val);
POSTING_READ(DPLL_CTRL1);
}

/* DDI -> PLL mapping */
val = I915_READ(DPLL_CTRL2);

Expand Down
12 changes: 3 additions & 9 deletions drivers/gpu/drm/i915/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -9771,21 +9771,15 @@ static void skylake_get_ddi_pll(struct drm_i915_private *dev_priv,
struct intel_crtc_state *pipe_config)
{
enum intel_dpll_id id;
u32 temp, dpll_ctl1;
u32 temp;

temp = I915_READ(DPLL_CTRL2) & DPLL_CTRL2_DDI_CLK_SEL_MASK(port);
pipe_config->ddi_pll_sel = temp >> (port * 3 + 1);

switch (pipe_config->ddi_pll_sel) {
case SKL_DPLL0:
/*
* On SKL the eDP DPLL (DPLL0 as we don't use SSC) is not part
* of the shared DPLL framework and thus needs to be read out
* separately
*/
dpll_ctl1 = I915_READ(DPLL_CTRL1);
pipe_config->dpll_hw_state.ctrl1 = dpll_ctl1 & 0x3f;
return;
id = DPLL_ID_SKL_DPLL0;
break;
case SKL_DPLL1:
id = DPLL_ID_SKL_DPLL1;
break;
Expand Down
52 changes: 1 addition & 51 deletions drivers/gpu/drm/i915/intel_dp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1237,52 +1237,6 @@ intel_dp_connector_unregister(struct intel_connector *intel_connector)
intel_connector_unregister(intel_connector);
}

static void
skl_edp_set_pll_config(struct intel_crtc_state *pipe_config)
{
u32 ctrl1;

memset(&pipe_config->dpll_hw_state, 0,
sizeof(pipe_config->dpll_hw_state));

pipe_config->ddi_pll_sel = SKL_DPLL0;
pipe_config->dpll_hw_state.cfgcr1 = 0;
pipe_config->dpll_hw_state.cfgcr2 = 0;

ctrl1 = DPLL_CTRL1_OVERRIDE(SKL_DPLL0);
switch (pipe_config->port_clock / 2) {
case 81000:
ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810,
SKL_DPLL0);
break;
case 135000:
ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350,
SKL_DPLL0);
break;
case 270000:
ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700,
SKL_DPLL0);
break;
case 162000:
ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620,
SKL_DPLL0);
break;
/* TBD: For DP link rates 2.16 GHz and 4.32 GHz, VCO is 8640 which
results in CDCLK change. Need to handle the change of CDCLK by
disabling pipes and re-enabling them */
case 108000:
ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080,
SKL_DPLL0);
break;
case 216000:
ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160,
SKL_DPLL0);
break;

}
pipe_config->dpll_hw_state.ctrl1 = ctrl1;
}

static int
intel_dp_sink_rates(struct intel_dp *intel_dp, const int **sink_rates)
{
Expand Down Expand Up @@ -1640,11 +1594,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
&pipe_config->dp_m2_n2);
}

if ((IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) && is_edp(intel_dp))
skl_edp_set_pll_config(pipe_config);
else if (IS_BROXTON(dev) || IS_HASWELL(dev) || IS_BROADWELL(dev))
/* handled in ddi */;
else
if (!HAS_DDI(dev))
intel_dp_set_clock(encoder, pipe_config);

return true;
Expand Down
124 changes: 97 additions & 27 deletions drivers/gpu/drm/i915/intel_dpll_mgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -785,7 +785,12 @@ struct skl_dpll_regs {
};

/* this array is indexed by the *shared* pll id */
static const struct skl_dpll_regs skl_dpll_regs[3] = {
static const struct skl_dpll_regs skl_dpll_regs[4] = {
{
/* DPLL 0 */
.ctl = LCPLL1_CTL,
/* DPLL 0 doesn't support HDMI mode */
},
{
/* DPLL 1 */
.ctl = LCPLL2_CTL,
Expand All @@ -806,24 +811,27 @@ static const struct skl_dpll_regs skl_dpll_regs[3] = {
},
};

static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv,
struct intel_shared_dpll *pll)
static void skl_ddi_pll_write_ctrl1(struct drm_i915_private *dev_priv,
struct intel_shared_dpll *pll)
{
uint32_t val;
unsigned int dpll;
const struct skl_dpll_regs *regs = skl_dpll_regs;

/* DPLL0 is not part of the shared DPLLs, so pll->id is 0 for DPLL1 */
dpll = pll->id + 1;

val = I915_READ(DPLL_CTRL1);

val &= ~(DPLL_CTRL1_HDMI_MODE(dpll) | DPLL_CTRL1_SSC(dpll) |
DPLL_CTRL1_LINK_RATE_MASK(dpll));
val |= pll->config.hw_state.ctrl1 << (dpll * 6);
val &= ~(DPLL_CTRL1_HDMI_MODE(pll->id) | DPLL_CTRL1_SSC(pll->id) |
DPLL_CTRL1_LINK_RATE_MASK(pll->id));
val |= pll->config.hw_state.ctrl1 << (pll->id * 6);

I915_WRITE(DPLL_CTRL1, val);
POSTING_READ(DPLL_CTRL1);
}

static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv,
struct intel_shared_dpll *pll)
{
const struct skl_dpll_regs *regs = skl_dpll_regs;

skl_ddi_pll_write_ctrl1(dev_priv, pll);

I915_WRITE(regs[pll->id].cfgcr1, pll->config.hw_state.cfgcr1);
I915_WRITE(regs[pll->id].cfgcr2, pll->config.hw_state.cfgcr2);
Expand All @@ -834,8 +842,14 @@ static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv,
I915_WRITE(regs[pll->id].ctl,
I915_READ(regs[pll->id].ctl) | LCPLL_PLL_ENABLE);

if (wait_for(I915_READ(DPLL_STATUS) & DPLL_LOCK(dpll), 5))
DRM_ERROR("DPLL %d not locked\n", dpll);
if (wait_for(I915_READ(DPLL_STATUS) & DPLL_LOCK(pll->id), 5))
DRM_ERROR("DPLL %d not locked\n", pll->id);
}

static void skl_ddi_dpll0_enable(struct drm_i915_private *dev_priv,
struct intel_shared_dpll *pll)
{
skl_ddi_pll_write_ctrl1(dev_priv, pll);
}

static void skl_ddi_pll_disable(struct drm_i915_private *dev_priv,
Expand All @@ -849,12 +863,16 @@ static void skl_ddi_pll_disable(struct drm_i915_private *dev_priv,
POSTING_READ(regs[pll->id].ctl);
}

static void skl_ddi_dpll0_disable(struct drm_i915_private *dev_priv,
struct intel_shared_dpll *pll)
{
}

static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
struct intel_shared_dpll *pll,
struct intel_dpll_hw_state *hw_state)
{
uint32_t val;
unsigned int dpll;
const struct skl_dpll_regs *regs = skl_dpll_regs;
bool ret;

Expand All @@ -863,18 +881,15 @@ static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,

ret = false;

/* DPLL0 is not part of the shared DPLLs, so pll->id is 0 for DPLL1 */
dpll = pll->id + 1;

val = I915_READ(regs[pll->id].ctl);
if (!(val & LCPLL_PLL_ENABLE))
goto out;

val = I915_READ(DPLL_CTRL1);
hw_state->ctrl1 = (val >> (dpll * 6)) & 0x3f;
hw_state->ctrl1 = (val >> (pll->id * 6)) & 0x3f;

/* avoid reading back stale values if HDMI mode is not enabled */
if (val & DPLL_CTRL1_HDMI_MODE(dpll)) {
if (val & DPLL_CTRL1_HDMI_MODE(pll->id)) {
hw_state->cfgcr1 = I915_READ(regs[pll->id].cfgcr1);
hw_state->cfgcr2 = I915_READ(regs[pll->id].cfgcr2);
}
Expand All @@ -886,6 +901,35 @@ static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
return ret;
}

static bool skl_ddi_dpll0_get_hw_state(struct drm_i915_private *dev_priv,
struct intel_shared_dpll *pll,
struct intel_dpll_hw_state *hw_state)
{
uint32_t val;
const struct skl_dpll_regs *regs = skl_dpll_regs;
bool ret;

if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
return false;

ret = false;

/* DPLL0 is always enabled since it drives CDCLK */
val = I915_READ(regs[pll->id].ctl);
if (WARN_ON(!(val & LCPLL_PLL_ENABLE)))
goto out;

val = I915_READ(DPLL_CTRL1);
hw_state->ctrl1 = (val >> (pll->id * 6)) & 0x3f;

ret = true;

out:
intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);

return ret;
}

struct skl_wrpll_context {
uint64_t min_deviation; /* current minimal deviation */
uint64_t central_freq; /* chosen central freq */
Expand Down Expand Up @@ -1165,7 +1209,8 @@ skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
DPLL_CFGCR2_PDIV(wrpll_params.pdiv) |
wrpll_params.central_freq;
} else if (encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
encoder->type == INTEL_OUTPUT_DP_MST) {
encoder->type == INTEL_OUTPUT_DP_MST ||
encoder->type == INTEL_OUTPUT_EDP) {
switch (crtc_state->port_clock / 2) {
case 81000:
ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, 0);
Expand All @@ -1176,6 +1221,19 @@ skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
case 270000:
ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, 0);
break;
/* eDP 1.4 rates */
case 162000:
ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, 0);
break;
/* TBD: For DP link rates 2.16 GHz and 4.32 GHz, VCO is 8640 which
results in CDCLK change. Need to handle the change of CDCLK by
disabling pipes and re-enabling them */
case 108000:
ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, 0);
break;
case 216000:
ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, 0);
break;
}

cfgcr1 = cfgcr2 = 0;
Expand All @@ -1190,13 +1248,18 @@ skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
crtc_state->dpll_hw_state.cfgcr1 = cfgcr1;
crtc_state->dpll_hw_state.cfgcr2 = cfgcr2;

pll = intel_find_shared_dpll(crtc, crtc_state,
DPLL_ID_SKL_DPLL1, DPLL_ID_SKL_DPLL3);
if (encoder->type == INTEL_OUTPUT_EDP)
pll = intel_find_shared_dpll(crtc, crtc_state,
DPLL_ID_SKL_DPLL0,
DPLL_ID_SKL_DPLL0);
else
pll = intel_find_shared_dpll(crtc, crtc_state,
DPLL_ID_SKL_DPLL1,
DPLL_ID_SKL_DPLL3);
if (!pll)
return NULL;

/* shared DPLL id 0 is DPLL 1 */
crtc_state->ddi_pll_sel = pll->id + 1;
crtc_state->ddi_pll_sel = pll->id;

intel_reference_shared_dpll(pll, crtc_state);

Expand All @@ -1209,6 +1272,12 @@ static const struct intel_shared_dpll_funcs skl_ddi_pll_funcs = {
.get_hw_state = skl_ddi_pll_get_hw_state,
};

static const struct intel_shared_dpll_funcs skl_ddi_dpll0_funcs = {
.enable = skl_ddi_dpll0_enable,
.disable = skl_ddi_dpll0_disable,
.get_hw_state = skl_ddi_dpll0_get_hw_state,
};

static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv,
struct intel_shared_dpll *pll)
{
Expand Down Expand Up @@ -1624,9 +1693,10 @@ static const struct intel_dpll_mgr hsw_pll_mgr = {
};

static const struct dpll_info skl_plls[] = {
{ "DPPL 1", DPLL_ID_SKL_DPLL1, &skl_ddi_pll_funcs, 0 },
{ "DPPL 2", DPLL_ID_SKL_DPLL2, &skl_ddi_pll_funcs, 0 },
{ "DPPL 3", DPLL_ID_SKL_DPLL3, &skl_ddi_pll_funcs, 0 },
{ "DPLL 0", DPLL_ID_SKL_DPLL0, &skl_ddi_dpll0_funcs, INTEL_DPLL_ALWAYS_ON },
{ "DPPL 1", DPLL_ID_SKL_DPLL1, &skl_ddi_pll_funcs, 0 },
{ "DPPL 2", DPLL_ID_SKL_DPLL2, &skl_ddi_pll_funcs, 0 },
{ "DPPL 3", DPLL_ID_SKL_DPLL3, &skl_ddi_pll_funcs, 0 },
{ NULL, -1, NULL, },
};

Expand Down
7 changes: 4 additions & 3 deletions drivers/gpu/drm/i915/intel_dpll_mgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,10 @@ enum intel_dpll_id {
DPLL_ID_LCPLL_2700 = 5,

/* skl */
DPLL_ID_SKL_DPLL1 = 0,
DPLL_ID_SKL_DPLL2 = 1,
DPLL_ID_SKL_DPLL3 = 2,
DPLL_ID_SKL_DPLL0 = 0,
DPLL_ID_SKL_DPLL1 = 1,
DPLL_ID_SKL_DPLL2 = 2,
DPLL_ID_SKL_DPLL3 = 3,
};
#define I915_NUM_PLLS 6

Expand Down

0 comments on commit a3c988e

Please sign in to comment.