drm/i915: Manage HSW/BDW LCPLLs with the shared dpll interface
Manage the LCPLLs used with DisplayPort, so that all the HSW/BDW DPLLs are managed by the shared dpll code. v2: Introduce INTEL_DPLL_ALWAYS_ON flag to please state checker. (Ander) v3: Initialize pll->flags in intel_shared_dpll_init(). (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-13-git-send-email-ander.conselvan.de.oliveira@intel.com
This commit is contained in:
parent
34177c249a
commit
9d16da65bf
|
@ -992,17 +992,13 @@ hsw_ddi_pll_select(struct intel_crtc *intel_crtc,
|
|||
{
|
||||
struct intel_shared_dpll *pll;
|
||||
|
||||
if (intel_encoder->type == INTEL_OUTPUT_HDMI ||
|
||||
intel_encoder->type == INTEL_OUTPUT_ANALOG) {
|
||||
pll = intel_get_shared_dpll(intel_crtc, crtc_state,
|
||||
intel_encoder);
|
||||
if (!pll)
|
||||
DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
|
||||
pipe_name(intel_crtc->pipe));
|
||||
return pll;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
pll = intel_get_shared_dpll(intel_crtc, crtc_state,
|
||||
intel_encoder);
|
||||
if (!pll)
|
||||
DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
|
||||
pipe_name(intel_crtc->pipe));
|
||||
|
||||
return pll;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
|
@ -9821,13 +9821,19 @@ static void haswell_get_ddi_pll(struct drm_i915_private *dev_priv,
|
|||
case PORT_CLK_SEL_SPLL:
|
||||
id = DPLL_ID_SPLL;
|
||||
break;
|
||||
case PORT_CLK_SEL_LCPLL_810:
|
||||
id = DPLL_ID_LCPLL_810;
|
||||
break;
|
||||
case PORT_CLK_SEL_LCPLL_1350:
|
||||
id = DPLL_ID_LCPLL_1350;
|
||||
break;
|
||||
case PORT_CLK_SEL_LCPLL_2700:
|
||||
id = DPLL_ID_LCPLL_2700;
|
||||
break;
|
||||
default:
|
||||
MISSING_CASE(pipe_config->ddi_pll_sel);
|
||||
/* fall through */
|
||||
case PORT_CLK_SEL_NONE:
|
||||
case PORT_CLK_SEL_LCPLL_810:
|
||||
case PORT_CLK_SEL_LCPLL_1350:
|
||||
case PORT_CLK_SEL_LCPLL_2700:
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -12942,11 +12948,14 @@ check_shared_dpll_state(struct drm_device *dev)
|
|||
pll->active, hweight32(pll->config.crtc_mask));
|
||||
I915_STATE_WARN(pll->active && !pll->on,
|
||||
"pll in active use but not on in sw tracking\n");
|
||||
I915_STATE_WARN(pll->on && !pll->active,
|
||||
"pll in on but not on in use in sw tracking\n");
|
||||
I915_STATE_WARN(pll->on != active,
|
||||
"pll on state mismatch (expected %i, found %i)\n",
|
||||
pll->on, active);
|
||||
|
||||
if (!(pll->flags & INTEL_DPLL_ALWAYS_ON)) {
|
||||
I915_STATE_WARN(pll->on && !pll->active,
|
||||
"pll in on but not on in use in sw tracking\n");
|
||||
I915_STATE_WARN(pll->on != active,
|
||||
"pll on state mismatch (expected %i, found %i)\n",
|
||||
pll->on, active);
|
||||
}
|
||||
|
||||
for_each_intel_crtc(dev, crtc) {
|
||||
if (crtc->base.state->enable && crtc->config->shared_dpll == pll)
|
||||
|
|
|
@ -1283,25 +1283,6 @@ skl_edp_set_pll_config(struct intel_crtc_state *pipe_config)
|
|||
pipe_config->dpll_hw_state.ctrl1 = ctrl1;
|
||||
}
|
||||
|
||||
void
|
||||
hsw_dp_set_ddi_pll_sel(struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
memset(&pipe_config->dpll_hw_state, 0,
|
||||
sizeof(pipe_config->dpll_hw_state));
|
||||
|
||||
switch (pipe_config->port_clock / 2) {
|
||||
case 81000:
|
||||
pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_810;
|
||||
break;
|
||||
case 135000:
|
||||
pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_1350;
|
||||
break;
|
||||
case 270000:
|
||||
pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_2700;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
intel_dp_sink_rates(struct intel_dp *intel_dp, const int **sink_rates)
|
||||
{
|
||||
|
@ -1661,10 +1642,8 @@ found:
|
|||
|
||||
if ((IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) && is_edp(intel_dp))
|
||||
skl_edp_set_pll_config(pipe_config);
|
||||
else if (IS_BROXTON(dev))
|
||||
else if (IS_BROXTON(dev) || IS_HASWELL(dev) || IS_BROADWELL(dev))
|
||||
/* handled in ddi */;
|
||||
else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
|
||||
hsw_dp_set_ddi_pll_sel(pipe_config);
|
||||
else
|
||||
intel_dp_set_clock(encoder, pipe_config);
|
||||
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
struct drm_device *dev = encoder->base.dev;
|
||||
struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
|
||||
struct intel_digital_port *intel_dig_port = intel_mst->primary;
|
||||
struct intel_dp *intel_dp = &intel_dig_port->dp;
|
||||
|
@ -92,9 +91,6 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
|
|||
|
||||
pipe_config->dp_m_n.tu = slots;
|
||||
|
||||
if (IS_HASWELL(dev) || IS_BROADWELL(dev))
|
||||
hsw_dp_set_ddi_pll_sel(pipe_config);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
|
|
@ -447,6 +447,12 @@ static uint32_t hsw_pll_to_ddi_pll_sel(struct intel_shared_dpll *pll)
|
|||
return PORT_CLK_SEL_WRPLL2;
|
||||
case DPLL_ID_SPLL:
|
||||
return PORT_CLK_SEL_SPLL;
|
||||
case DPLL_ID_LCPLL_810:
|
||||
return PORT_CLK_SEL_LCPLL_810;
|
||||
case DPLL_ID_LCPLL_1350:
|
||||
return PORT_CLK_SEL_LCPLL_1350;
|
||||
case DPLL_ID_LCPLL_2700:
|
||||
return PORT_CLK_SEL_LCPLL_2700;
|
||||
default:
|
||||
return PORT_CLK_SEL_NONE;
|
||||
}
|
||||
|
@ -671,9 +677,13 @@ static struct intel_shared_dpll *
|
|||
hsw_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
|
||||
struct intel_encoder *encoder)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
struct intel_shared_dpll *pll;
|
||||
int clock = crtc_state->port_clock;
|
||||
|
||||
memset(&crtc_state->dpll_hw_state, 0,
|
||||
sizeof(crtc_state->dpll_hw_state));
|
||||
|
||||
if (encoder->type == INTEL_OUTPUT_HDMI) {
|
||||
uint32_t val;
|
||||
unsigned p, n2, r2;
|
||||
|
@ -684,21 +694,37 @@ hsw_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
|
|||
WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
|
||||
WRPLL_DIVIDER_POST(p);
|
||||
|
||||
memset(&crtc_state->dpll_hw_state, 0,
|
||||
sizeof(crtc_state->dpll_hw_state));
|
||||
|
||||
crtc_state->dpll_hw_state.wrpll = val;
|
||||
|
||||
pll = intel_find_shared_dpll(crtc, crtc_state,
|
||||
DPLL_ID_WRPLL1, DPLL_ID_WRPLL2);
|
||||
|
||||
} else if (encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
|
||||
encoder->type == INTEL_OUTPUT_DP_MST ||
|
||||
encoder->type == INTEL_OUTPUT_EDP) {
|
||||
enum intel_dpll_id pll_id;
|
||||
|
||||
switch (clock / 2) {
|
||||
case 81000:
|
||||
pll_id = DPLL_ID_LCPLL_810;
|
||||
break;
|
||||
case 135000:
|
||||
pll_id = DPLL_ID_LCPLL_1350;
|
||||
break;
|
||||
case 270000:
|
||||
pll_id = DPLL_ID_LCPLL_2700;
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG_KMS("Invalid clock for DP: %d\n", clock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pll = intel_get_shared_dpll_by_id(dev_priv, pll_id);
|
||||
|
||||
} else if (encoder->type == INTEL_OUTPUT_ANALOG) {
|
||||
if (WARN_ON(crtc_state->port_clock / 2 != 135000))
|
||||
return NULL;
|
||||
|
||||
memset(&crtc_state->dpll_hw_state, 0,
|
||||
sizeof(crtc_state->dpll_hw_state));
|
||||
|
||||
crtc_state->dpll_hw_state.spll =
|
||||
SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC;
|
||||
|
||||
|
@ -731,6 +757,29 @@ static const struct intel_shared_dpll_funcs hsw_ddi_spll_funcs = {
|
|||
.get_hw_state = hsw_ddi_spll_get_hw_state,
|
||||
};
|
||||
|
||||
static void hsw_ddi_lcpll_enable(struct drm_i915_private *dev_priv,
|
||||
struct intel_shared_dpll *pll)
|
||||
{
|
||||
}
|
||||
|
||||
static void hsw_ddi_lcpll_disable(struct drm_i915_private *dev_priv,
|
||||
struct intel_shared_dpll *pll)
|
||||
{
|
||||
}
|
||||
|
||||
static bool hsw_ddi_lcpll_get_hw_state(struct drm_i915_private *dev_priv,
|
||||
struct intel_shared_dpll *pll,
|
||||
struct intel_dpll_hw_state *hw_state)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static const struct intel_shared_dpll_funcs hsw_ddi_lcpll_funcs = {
|
||||
.enable = hsw_ddi_lcpll_enable,
|
||||
.disable = hsw_ddi_lcpll_disable,
|
||||
.get_hw_state = hsw_ddi_lcpll_get_hw_state,
|
||||
};
|
||||
|
||||
struct skl_dpll_regs {
|
||||
i915_reg_t ctl, cfgcr1, cfgcr2;
|
||||
};
|
||||
|
@ -1537,6 +1586,7 @@ struct dpll_info {
|
|||
const char *name;
|
||||
const int id;
|
||||
const struct intel_shared_dpll_funcs *funcs;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
struct intel_dpll_mgr {
|
||||
|
@ -1548,9 +1598,9 @@ struct intel_dpll_mgr {
|
|||
};
|
||||
|
||||
static const struct dpll_info pch_plls[] = {
|
||||
{ "PCH DPLL A", DPLL_ID_PCH_PLL_A, &ibx_pch_dpll_funcs },
|
||||
{ "PCH DPLL B", DPLL_ID_PCH_PLL_B, &ibx_pch_dpll_funcs },
|
||||
{ NULL, -1, NULL },
|
||||
{ "PCH DPLL A", DPLL_ID_PCH_PLL_A, &ibx_pch_dpll_funcs, 0 },
|
||||
{ "PCH DPLL B", DPLL_ID_PCH_PLL_B, &ibx_pch_dpll_funcs, 0 },
|
||||
{ NULL, -1, NULL, 0 },
|
||||
};
|
||||
|
||||
static const struct intel_dpll_mgr pch_pll_mgr = {
|
||||
|
@ -1559,9 +1609,12 @@ static const struct intel_dpll_mgr pch_pll_mgr = {
|
|||
};
|
||||
|
||||
static const struct dpll_info hsw_plls[] = {
|
||||
{ "WRPLL 1", DPLL_ID_WRPLL1, &hsw_ddi_wrpll_funcs },
|
||||
{ "WRPLL 2", DPLL_ID_WRPLL2, &hsw_ddi_wrpll_funcs },
|
||||
{ "SPLL", DPLL_ID_SPLL, &hsw_ddi_spll_funcs },
|
||||
{ "WRPLL 1", DPLL_ID_WRPLL1, &hsw_ddi_wrpll_funcs, 0 },
|
||||
{ "WRPLL 2", DPLL_ID_WRPLL2, &hsw_ddi_wrpll_funcs, 0 },
|
||||
{ "SPLL", DPLL_ID_SPLL, &hsw_ddi_spll_funcs, 0 },
|
||||
{ "LCPLL 810", DPLL_ID_LCPLL_810, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
|
||||
{ "LCPLL 1350", DPLL_ID_LCPLL_1350, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
|
||||
{ "LCPLL 2700", DPLL_ID_LCPLL_2700, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
|
||||
{ NULL, -1, NULL, },
|
||||
};
|
||||
|
||||
|
@ -1571,9 +1624,9 @@ 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 },
|
||||
{ "DPPL 2", DPLL_ID_SKL_DPLL2, &skl_ddi_pll_funcs },
|
||||
{ "DPPL 3", DPLL_ID_SKL_DPLL3, &skl_ddi_pll_funcs },
|
||||
{ "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, },
|
||||
};
|
||||
|
||||
|
@ -1583,9 +1636,9 @@ static const struct intel_dpll_mgr skl_pll_mgr = {
|
|||
};
|
||||
|
||||
static const struct dpll_info bxt_plls[] = {
|
||||
{ "PORT PLL A", 0, &bxt_ddi_pll_funcs },
|
||||
{ "PORT PLL B", 1, &bxt_ddi_pll_funcs },
|
||||
{ "PORT PLL C", 2, &bxt_ddi_pll_funcs },
|
||||
{ "PORT PLL A", 0, &bxt_ddi_pll_funcs, 0 },
|
||||
{ "PORT PLL B", 1, &bxt_ddi_pll_funcs, 0 },
|
||||
{ "PORT PLL C", 2, &bxt_ddi_pll_funcs, 0 },
|
||||
{ NULL, -1, NULL, },
|
||||
};
|
||||
|
||||
|
@ -1623,6 +1676,7 @@ void intel_shared_dpll_init(struct drm_device *dev)
|
|||
dev_priv->shared_dplls[i].id = dpll_info[i].id;
|
||||
dev_priv->shared_dplls[i].name = dpll_info[i].name;
|
||||
dev_priv->shared_dplls[i].funcs = *dpll_info[i].funcs;
|
||||
dev_priv->shared_dplls[i].flags = dpll_info[i].flags;
|
||||
}
|
||||
|
||||
dev_priv->dpll_mgr = dpll_mgr;
|
||||
|
|
|
@ -49,13 +49,21 @@ enum intel_dpll_id {
|
|||
DPLL_ID_WRPLL1 = 0,
|
||||
DPLL_ID_WRPLL2 = 1,
|
||||
DPLL_ID_SPLL = 2,
|
||||
DPLL_ID_LCPLL_810 = 3,
|
||||
DPLL_ID_LCPLL_1350 = 4,
|
||||
DPLL_ID_LCPLL_2700 = 5,
|
||||
|
||||
/* skl */
|
||||
DPLL_ID_SKL_DPLL1 = 0,
|
||||
DPLL_ID_SKL_DPLL2 = 1,
|
||||
DPLL_ID_SKL_DPLL3 = 2,
|
||||
};
|
||||
#define I915_NUM_PLLS 3
|
||||
#define I915_NUM_PLLS 6
|
||||
|
||||
/** Inform the state checker that the DPLL is kept enabled even if not
|
||||
* in use by any crtc.
|
||||
*/
|
||||
#define INTEL_DPLL_ALWAYS_ON (1 << 0)
|
||||
|
||||
struct intel_dpll_hw_state {
|
||||
/* i9xx, pch plls */
|
||||
|
@ -113,6 +121,8 @@ struct intel_shared_dpll {
|
|||
enum intel_dpll_id id;
|
||||
|
||||
struct intel_shared_dpll_funcs funcs;
|
||||
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
#define SKL_DPLL0 0
|
||||
|
|
|
@ -1312,7 +1312,6 @@ void intel_edp_drrs_invalidate(struct drm_device *dev,
|
|||
void intel_edp_drrs_flush(struct drm_device *dev, unsigned frontbuffer_bits);
|
||||
bool intel_digital_port_connected(struct drm_i915_private *dev_priv,
|
||||
struct intel_digital_port *port);
|
||||
void hsw_dp_set_ddi_pll_sel(struct intel_crtc_state *pipe_config);
|
||||
|
||||
void
|
||||
intel_dp_program_link_training_pattern(struct intel_dp *intel_dp,
|
||||
|
|
Loading…
Reference in New Issue