[PATCH 16/19] WIP: chv shared pll
Ander Conselvan de Oliveira
ander.conselvan.de.oliveira at intel.com
Mon May 9 09:44:08 UTC 2016
---
drivers/gpu/drm/i915/i915_drv.h | 5 +-
drivers/gpu/drm/i915/intel_display.c | 142 +++++++-------------------------
drivers/gpu/drm/i915/intel_dpio_phy.c | 7 +-
drivers/gpu/drm/i915/intel_dpll_mgr.c | 147 ++++++++++++++++++++++++++++++++++
4 files changed, 182 insertions(+), 119 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 22f8c13..174aa5b 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -3596,8 +3596,9 @@ void chv_phy_pre_pll_enable(struct intel_encoder *encoder);
void chv_phy_pre_encoder_enable(struct intel_encoder *encoder);
void chv_phy_release_cl2_override(struct intel_encoder *encoder);
void chv_phy_post_pll_disable(struct intel_encoder *encoder);
-void chv_phy_prepare_pll(struct intel_crtc *crtc, u32 bestn,
- u32 bestm1, u32 bestm2, u32 bestp1, u32 bestp2,
+void chv_phy_prepare_pll(struct drm_i915_private *dev_priv, enum pipe pipe,
+ u32 bestn, u32 bestm1, u32 bestm2,
+ u32 bestp1, u32 bestp2,
int vco);
void chv_phy_toggle_dclkp(struct drm_i915_private *dev_priv, enum pipe pipe,
bool enable);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index e9dbe89..b395db9 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1524,59 +1524,6 @@ static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv,
}
-static void _chv_enable_pll(struct intel_crtc *crtc,
- const struct intel_crtc_state *pipe_config)
-{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- enum pipe pipe = crtc->pipe;
-
- /* Enable back the 10bit clock to display controller */
- chv_phy_toggle_dclkp(dev_priv, pipe, true);
-
- /*
- * Need to wait > 100ns between dclkp clock enable bit and PLL enable.
- */
- udelay(1);
-
- /* Enable PLL */
- I915_WRITE(DPLL(pipe), pipe_config->dpll_hw_state.dpll);
-
- /* Check PLL is locked */
- if (wait_for(((I915_READ(DPLL(pipe)) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1))
- DRM_ERROR("PLL %d failed to lock\n", pipe);
-}
-
-static void chv_enable_pll(struct intel_crtc *crtc,
- const struct intel_crtc_state *pipe_config)
-{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- enum pipe pipe = crtc->pipe;
-
- /* Enable Refclk and SSC */
- I915_WRITE(DPLL(pipe),
- pipe_config->dpll_hw_state.dpll & ~DPLL_VCO_ENABLE);
-
- /* No need to actually set up the DPLL with DSI */
- if ((pipe_config->dpll_hw_state.dpll & DPLL_VCO_ENABLE) != 0) {
- const struct dpll *dividers =
- &pipe_config->dpll_hw_state.dividers;
-
- chv_phy_prepare_pll(crtc, dividers->n,
- dividers->m1, dividers->m2,
- dividers->p1, dividers->p2,
- dividers->vco);
- }
-
- assert_pipe_disabled(dev_priv, pipe);
-
- /* PLL is protected by panel, make sure we can write it */
- assert_panel_unlocked(dev_priv, pipe);
-
- if (pipe_config->dpll_hw_state.dpll & DPLL_VCO_ENABLE)
- _chv_enable_pll(crtc, pipe_config);
-
-}
-
static int intel_num_dvo_pipes(struct drm_device *dev)
{
struct intel_crtc *crtc;
@@ -1689,25 +1636,6 @@ static void i9xx_disable_pll(struct intel_crtc *crtc)
POSTING_READ(DPLL(pipe));
}
-static void chv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
-{
- u32 val;
-
- /* Make sure the pipe isn't still relying on us */
- assert_pipe_disabled(dev_priv, pipe);
-
- val = DPLL_SSC_REF_CLK_CHV |
- DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS;
- if (pipe != PIPE_A)
- val |= DPLL_INTEGRATED_CRI_CLK_VLV;
-
- I915_WRITE(DPLL(pipe), val);
- POSTING_READ(DPLL(pipe));
-
- /* Disable 10bit clock to display controller */
- chv_phy_toggle_dclkp(dev_priv, pipe, false);
-}
-
void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
struct intel_digital_port *dport,
unsigned int expected_mask)
@@ -6050,9 +5978,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
if (encoder->pre_pll_enable)
encoder->pre_pll_enable(encoder);
- if (IS_CHERRYVIEW(dev))
- chv_enable_pll(intel_crtc, intel_crtc->config);
- else if (!pipe_config->has_dsi_encoder)
+ if (!pipe_config->has_dsi_encoder)
intel_enable_shared_dpll(intel_crtc);
vlv_crtc_set_pixel_multiplier(intel_crtc);
@@ -6177,9 +6103,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
encoder->post_disable(encoder);
if (!intel_crtc->config->has_dsi_encoder) {
- if (IS_CHERRYVIEW(dev))
- chv_disable_pll(dev_priv, pipe);
- else if (IS_VALLEYVIEW(dev))
+ if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
intel_disable_shared_dpll(intel_crtc);
else
i9xx_disable_pll(intel_crtc);
@@ -7169,6 +7093,7 @@ int vlv_force_pll_on(struct drm_device *dev, enum pipe pipe,
struct intel_crtc *crtc =
to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe));
struct intel_crtc_state *pipe_config;
+ struct intel_shared_dpll *pll;
pipe_config = kzalloc(sizeof(*pipe_config), GFP_KERNEL);
if (!pipe_config)
@@ -7177,17 +7102,15 @@ int vlv_force_pll_on(struct drm_device *dev, enum pipe pipe,
pipe_config->base.crtc = &crtc->base;
pipe_config->dpll_hw_state.dividers = *dpll;
- if (IS_CHERRYVIEW(dev)) {
+ if (IS_CHERRYVIEW(dev))
chv_compute_dpll(crtc, pipe_config);
- chv_enable_pll(crtc, pipe_config);
- } else {
- struct intel_shared_dpll *pll =
- intel_get_shared_dpll_by_id(dev_priv, pipe);
-
+ else
vlv_compute_dpll(crtc, pipe_config);
- intel_shared_dpll_force_enable(dev_priv, pll,
- &pipe_config->dpll_hw_state);
- }
+
+ pll = intel_get_shared_dpll_by_id(dev_priv, pipe);
+
+ intel_shared_dpll_force_enable(dev_priv, pll,
+ &pipe_config->dpll_hw_state);
kfree(pipe_config);
@@ -7205,15 +7128,10 @@ int vlv_force_pll_on(struct drm_device *dev, enum pipe pipe,
void vlv_force_pll_off(struct drm_device *dev, enum pipe pipe)
{
struct drm_i915_private *dev_priv = to_i915(dev);
+ struct intel_shared_dpll *pll =
+ intel_get_shared_dpll_by_id(dev_priv, pipe);
- if (IS_CHERRYVIEW(dev)) {
- chv_disable_pll(to_i915(dev), pipe);
- } else {
- struct intel_shared_dpll *pll =
- intel_get_shared_dpll_by_id(dev_priv, pipe);
-
- intel_shared_dpll_force_disable(dev_priv, pll);
- }
+ intel_shared_dpll_force_disable(dev_priv, pll);
}
static void i9xx_compute_dpll(struct intel_crtc *crtc,
@@ -7731,6 +7649,7 @@ static int chv_crtc_compute_clock(struct intel_crtc *crtc,
{
int refclk = 100000;
const struct intel_limit *limit = &intel_limits_chv;
+ struct intel_shared_dpll *pll;
memset(&crtc_state->dpll_hw_state, 0,
sizeof(crtc_state->dpll_hw_state));
@@ -7745,6 +7664,14 @@ static int chv_crtc_compute_clock(struct intel_crtc *crtc,
chv_compute_dpll(crtc, crtc_state);
+ pll = intel_get_shared_dpll(crtc, crtc_state,
+ find_digital_encoder(crtc, crtc_state));
+ if (!crtc_state->has_dsi_encoder && !pll) {
+ DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
+ pipe_name(crtc->pipe));
+ return -EINVAL;
+ }
+
return 0;
}
@@ -7917,6 +7844,8 @@ static bool vlv_get_pipe_config(struct intel_crtc *crtc,
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
enum intel_display_power_domain power_domain;
+ struct intel_shared_dpll *pll;
+ bool enabled;
uint32_t tmp;
bool ret;
@@ -7964,26 +7893,13 @@ static bool vlv_get_pipe_config(struct intel_crtc *crtc,
((tmp & DPLL_MD_UDI_MULTIPLIER_MASK)
>> DPLL_MD_UDI_MULTIPLIER_SHIFT) + 1;
- if (IS_VALLEYVIEW(dev_priv)) {
- struct intel_shared_dpll *pll =
- intel_get_shared_dpll_by_id(dev_priv, crtc->pipe);
- bool enabled;
-
- enabled = pll->funcs.get_hw_state(dev_priv, pll,
- &pipe_config->dpll_hw_state);
+ pll = intel_get_shared_dpll_by_id(dev_priv, crtc->pipe);
- if (enabled)
- pipe_config->shared_dpll = pll;
- } else {
- pipe_config->dpll_hw_state.dpll_md = tmp;
+ enabled = pll->funcs.get_hw_state(dev_priv, pll,
+ &pipe_config->dpll_hw_state);
- pipe_config->dpll_hw_state.dpll = I915_READ(DPLL(crtc->pipe));
-
- /* Mask out read-only status bits. */
- pipe_config->dpll_hw_state.dpll &= ~(DPLL_LOCK_VLV |
- DPLL_PORTC_READY_MASK |
- DPLL_PORTB_READY_MASK);
- }
+ if (enabled)
+ pipe_config->shared_dpll = pll;
if (IS_CHERRYVIEW(dev))
chv_crtc_clock_get(crtc, pipe_config);
diff --git a/drivers/gpu/drm/i915/intel_dpio_phy.c b/drivers/gpu/drm/i915/intel_dpio_phy.c
index 438f1fff..da111fc 100644
--- a/drivers/gpu/drm/i915/intel_dpio_phy.c
+++ b/drivers/gpu/drm/i915/intel_dpio_phy.c
@@ -370,12 +370,11 @@ void chv_phy_post_pll_disable(struct intel_encoder *encoder)
chv_phy_powergate_lanes(encoder, false, 0x0);
}
-void chv_phy_prepare_pll(struct intel_crtc *crtc, u32 bestn,
- u32 bestm1, u32 bestm2, u32 bestp1, u32 bestp2,
+void chv_phy_prepare_pll(struct drm_i915_private *dev_priv, enum pipe pipe,
+ u32 bestn, u32 bestm1, u32 bestm2,
+ u32 bestp1, u32 bestp2,
int vco)
{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- enum pipe pipe = crtc->pipe;
enum dpio_channel port = vlv_pipe_to_channel(pipe);
u32 loopfilter, tribuf_calcntr;
u32 bestm2_frac;
diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c
index 5c99d23..2ffd74e 100644
--- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
+++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c
@@ -1844,6 +1844,139 @@ vlv_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
return pll;
}
+/* chv */
+static u32 chv_dpll_reg_value(struct drm_i915_private *dev_priv,
+ struct intel_shared_dpll *pll,
+ bool enabled)
+{
+ enum pipe pipe = pll->id;
+
+ /*
+ * The refclk should be kept enabled since it is required when driving
+ * a DSI output.
+ */
+ u32 dpll =
+ DPLL_SSC_REF_CLK_CHV |
+ DPLL_REF_CLK_ENABLE_VLV |
+ DPLL_VGA_MODE_DIS;
+
+ if (pipe != PIPE_A)
+ dpll |= DPLL_INTEGRATED_CRI_CLK_VLV;
+
+ if (enabled)
+ dpll |= DPLL_VCO_ENABLE;
+
+ return dpll;
+}
+
+static void chv_sanitize_pll(struct drm_i915_private *dev_priv,
+ struct intel_shared_dpll *pll)
+{
+ u32 dpll = chv_dpll_reg_value(dev_priv, pll, pll->on);
+ enum pipe pipe = pll->id;
+
+ I915_WRITE(DPLL(pipe), dpll);
+ POSTING_READ(DPLL(pipe));
+}
+
+static void chv_pll_enable(struct drm_i915_private *dev_priv,
+ struct intel_shared_dpll *pll)
+{
+ const struct dpll *dividers = &pll->config.hw_state.dividers;
+ enum pipe pipe = pll->id;
+
+ WARN_ON((pll->config.hw_state.dpll & DPLL_VCO_ENABLE) == 0);
+
+ assert_pipe_disabled(dev_priv, pipe);
+
+ /* PLL is protected by panel, make sure we can write it */
+ assert_panel_unlocked(dev_priv, pipe);
+
+ chv_phy_prepare_pll(dev_priv, pipe, dividers->n,
+ dividers->m1, dividers->m2,
+ dividers->p1, dividers->p2,
+ dividers->vco);
+
+ /* Enable back the 10bit clock to display controller */
+ chv_phy_toggle_dclkp(dev_priv, pipe, true);
+
+ /*
+ * Need to wait > 100ns between dclkp clock enable bit and PLL enable.
+ */
+ udelay(1);
+
+ /* Enable PLL */
+ I915_WRITE(DPLL(pipe), pll->config.hw_state.dpll);
+
+ /* Check PLL is locked */
+ if (wait_for(((I915_READ(DPLL(pipe)) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1))
+ DRM_ERROR("PLL %d failed to lock\n", pipe);
+}
+
+
+static void chv_pll_disable(struct drm_i915_private *dev_priv,
+ struct intel_shared_dpll *pll)
+{
+ enum pipe pipe = pll->id;
+ u32 val;
+
+ /* Make sure the pipe isn't still relying on us */
+ assert_pipe_disabled(dev_priv, pipe);
+
+ val = chv_dpll_reg_value(dev_priv, pll, false);
+ I915_WRITE(DPLL(pipe), val);
+ POSTING_READ(DPLL(pipe));
+
+ /* Disable 10bit clock to display controller */
+ chv_phy_toggle_dclkp(dev_priv, pipe, false);
+}
+
+static bool chv_pll_get_hw_state(struct drm_i915_private *dev_priv,
+ struct intel_shared_dpll *pll,
+ struct intel_dpll_hw_state *hw_state)
+{
+ enum pipe pipe = pll->id;
+ u32 read_only_bits =
+ DPLL_LOCK_VLV | DPLL_PORTC_READY_MASK | DPLL_PORTB_READY_MASK;
+
+ if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+ return false;
+
+ hw_state->dpll = I915_READ(DPLL(pipe)) & ~read_only_bits;
+
+ if (hw_state->dpll & DPLL_VCO_ENABLE)
+ chv_phy_read_dividers(dev_priv, pipe, &hw_state->dividers);
+
+ intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+
+ return hw_state->dpll & DPLL_VCO_ENABLE;
+}
+
+static const struct intel_shared_dpll_funcs chv_pll_funcs = {
+ .enable = chv_pll_enable,
+ .disable = chv_pll_disable,
+ .get_hw_state = chv_pll_get_hw_state,
+ .sanitize = chv_sanitize_pll,
+};
+
+static struct intel_shared_dpll *
+chv_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;
+
+ if (encoder->type == INTEL_OUTPUT_DSI) {
+ return NULL;
+ }
+
+ pll = intel_get_shared_dpll_by_id(dev_priv, crtc->pipe);
+
+ intel_reference_shared_dpll(pll, crtc_state);
+
+ return pll;
+}
+
/* --- */
struct dpll_info {
@@ -1923,6 +2056,18 @@ static const struct intel_dpll_mgr vlv_pll_mgr = {
.get_dpll = vlv_get_dpll,
};
+static const struct dpll_info chv_plls[] = {
+ { "PIPE A PLL", PIPE_A, &chv_pll_funcs, 0 },
+ { "PIPE B PLL", PIPE_B, &chv_pll_funcs, 0 },
+ { "PIPE C PLL", PIPE_C, &chv_pll_funcs, 0 },
+ { NULL, -1, NULL, },
+};
+
+static const struct intel_dpll_mgr chv_pll_mgr = {
+ .dpll_info = chv_plls,
+ .get_dpll = chv_get_dpll,
+};
+
void intel_shared_dpll_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1940,6 +2085,8 @@ void intel_shared_dpll_init(struct drm_device *dev)
dpll_mgr = &pch_pll_mgr;
else if (IS_VALLEYVIEW(dev))
dpll_mgr = &vlv_pll_mgr;
+ else if (IS_CHERRYVIEW(dev))
+ dpll_mgr = &chv_pll_mgr;
if (!dpll_mgr) {
dev_priv->num_shared_dpll = 0;
--
2.5.5
More information about the Intel-gfx-trybot
mailing list