Message ID | 1475584337-8900-8-git-send-email-ander.conselvan.de.oliveira@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Tue, Oct 04, 2016 at 03:32:17PM +0300, Ander Conselvan de Oliveira wrote: > Abstract the platform specific bits of mapping the dplls under a > platform independ entrypoints so the differences between platforms are > contained in the dpll code. I.e., it removes IS_PLATFORM() macros from > other parts of the code. > > Signed-off-by: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com> Not really sure this is worth it. This is all highly platform specific, adding abstraction just means even more hoops to jump through. But I spotted one thing while reading this. I know you're trying to consolidate the code here, but it feels a bit too much. At least I feel like the interactions between dpll and other code (i.e. how they link to encoders/crtc) is best left to that code. After all it's also that code that decides what kind of dpll setting it wants, the dpll mgr just figures out whether one is still available. -Daniel > --- > drivers/gpu/drm/i915/intel_ddi.c | 51 ++---- > drivers/gpu/drm/i915/intel_display.c | 124 +------------- > drivers/gpu/drm/i915/intel_dp_mst.c | 4 +- > drivers/gpu/drm/i915/intel_dpll_mgr.c | 299 ++++++++++++++++++++++++++++++++++ > drivers/gpu/drm/i915/intel_dpll_mgr.h | 7 + > drivers/gpu/drm/i915/intel_drv.h | 4 +- > 6 files changed, 334 insertions(+), 155 deletions(-) > > diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c > index 4077205..144fe5c 100644 > --- a/drivers/gpu/drm/i915/intel_ddi.c > +++ b/drivers/gpu/drm/i915/intel_ddi.c > @@ -319,6 +319,19 @@ enum port intel_ddi_get_encoder_port(struct intel_encoder *encoder) > } > } > > +struct intel_encoder * > +intel_ddi_get_port_encoder(struct drm_i915_private *dev_priv, enum port port) > +{ > + struct intel_encoder *encoder; > + > + for_each_intel_encoder(&dev_priv->drm, encoder) { > + if (port == intel_ddi_get_encoder_port(encoder)) > + return encoder; > + } > + > + return NULL; > +} > + > static const struct ddi_buf_trans * > bdw_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries) > { > @@ -582,11 +595,12 @@ void hsw_fdi_link_train(struct drm_crtc *crtc) > struct drm_i915_private *dev_priv = to_i915(dev); > struct intel_crtc *intel_crtc = to_intel_crtc(crtc); > struct intel_encoder *encoder; > - u32 temp, i, rx_ctl_val, ddi_pll_sel; > + u32 temp, i, rx_ctl_val; > > for_each_encoder_on_crtc(dev, crtc, encoder) { > WARN_ON(encoder->type != INTEL_OUTPUT_ANALOG); > intel_prepare_dp_ddi_buffers(encoder); > + break; > } > > /* Set the FDI_RX_MISC pwrdn lanes and the 2 workarounds listed at the > @@ -613,9 +627,7 @@ void hsw_fdi_link_train(struct drm_crtc *crtc) > I915_WRITE(FDI_RX_CTL(PIPE_A), rx_ctl_val); > > /* Configure Port Clock Select */ > - ddi_pll_sel = hsw_pll_to_ddi_pll_sel(intel_crtc->config->shared_dpll); > - I915_WRITE(PORT_CLK_SEL(PORT_E), ddi_pll_sel); > - WARN_ON(ddi_pll_sel != PORT_CLK_SEL_SPLL); > + intel_dpll_map_to_encoder(intel_crtc->config->shared_dpll, encoder); > > /* Start the training iterating through available voltages and emphasis, > * testing each value twice. */ > @@ -1607,33 +1619,6 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp) > return DDI_BUF_TRANS_SELECT(level); > } > > -void intel_ddi_clk_select(struct intel_encoder *encoder, > - struct intel_shared_dpll *pll) > -{ > - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); > - enum port port = intel_ddi_get_encoder_port(encoder); > - > - if (WARN_ON(!pll)) > - return; > - > - if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { > - uint32_t val; > - > - /* DDI -> PLL mapping */ > - val = I915_READ(DPLL_CTRL2); > - > - val &= ~(DPLL_CTRL2_DDI_CLK_OFF(port) | > - DPLL_CTRL2_DDI_CLK_SEL_MASK(port)); > - val |= (DPLL_CTRL2_DDI_CLK_SEL(pll->id, port) | > - DPLL_CTRL2_DDI_SEL_OVERRIDE(port)); > - > - I915_WRITE(DPLL_CTRL2, val); > - > - } else if (INTEL_INFO(dev_priv)->gen < 9) { > - I915_WRITE(PORT_CLK_SEL(port), hsw_pll_to_ddi_pll_sel(pll)); > - } > -} > - > static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder, > int link_rate, uint32_t lane_count, > struct intel_shared_dpll *pll, > @@ -1648,7 +1633,7 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder, > if (encoder->type == INTEL_OUTPUT_EDP) > intel_edp_panel_on(intel_dp); > > - intel_ddi_clk_select(encoder, pll); > + intel_dpll_map_to_encoder(pll, encoder); > intel_prepare_dp_ddi_buffers(encoder); > intel_ddi_init_dp_buf_reg(encoder); > intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); > @@ -1669,7 +1654,7 @@ static void intel_ddi_pre_enable_hdmi(struct intel_encoder *encoder, > int level = intel_ddi_hdmi_level(dev_priv, port); > > intel_dp_dual_mode_set_tmds_output(intel_hdmi, true); > - intel_ddi_clk_select(encoder, pll); > + intel_dpll_map_to_encoder(pll, encoder); > intel_prepare_hdmi_ddi_buffers(encoder); > if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) > skl_ddi_set_iboost(encoder, level); > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c > index 8ecaf18..22e3c46 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -4555,19 +4555,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) > > /* We need to program the right clock selection before writing the pixel > * mutliplier into the DPLL. */ > - if (HAS_PCH_CPT(dev)) { > - u32 sel; > - > - temp = I915_READ(PCH_DPLL_SEL); > - temp |= TRANS_DPLL_ENABLE(pipe); > - sel = TRANS_DPLLB_SEL(pipe); > - if (intel_crtc->config->shared_dpll == > - intel_get_shared_dpll_by_id(dev_priv, DPLL_ID_PCH_PLL_B)) > - temp |= sel; > - else > - temp &= ~sel; > - I915_WRITE(PCH_DPLL_SEL, temp); > - } > + intel_dpll_map_to_crtc(intel_crtc->config->shared_dpll, intel_crtc); > > /* XXX: pch pll's can be enabled any time before we enable the PCH > * transcoder, and we actually should do this to not upset any PCH > @@ -5574,9 +5562,7 @@ static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state, > I915_WRITE(reg, temp); > > /* disable DPLL_SEL */ > - temp = I915_READ(PCH_DPLL_SEL); > - temp &= ~(TRANS_DPLL_ENABLE(pipe) | TRANS_DPLLB_SEL(pipe)); > - I915_WRITE(PCH_DPLL_SEL, temp); > + intel_dpll_map_to_crtc(NULL, intel_crtc); > } > > ironlake_fdi_pll_disable(intel_crtc); > @@ -9952,7 +9938,6 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc, > > if (I915_READ(PCH_TRANSCONF(crtc->pipe)) & TRANS_ENABLE) { > struct intel_shared_dpll *pll; > - enum intel_dpll_id pll_id; > > pipe_config->has_pch_encoder = true; > > @@ -9962,23 +9947,7 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc, > > ironlake_get_fdi_m_n_config(crtc, pipe_config); > > - if (HAS_PCH_IBX(dev_priv)) { > - /* > - * The pipe->pch transcoder and pch transcoder->pll > - * mapping is fixed. > - */ > - pll_id = (enum intel_dpll_id) crtc->pipe; > - } else { > - tmp = I915_READ(PCH_DPLL_SEL); > - if (tmp & TRANS_DPLLB_SEL(crtc->pipe)) > - pll_id = DPLL_ID_PCH_PLL_B; > - else > - pll_id= DPLL_ID_PCH_PLL_A; > - } > - > - pipe_config->shared_dpll = > - intel_get_shared_dpll_by_id(dev_priv, pll_id); > - pll = pipe_config->shared_dpll; > + pipe_config->shared_dpll = pll = intel_get_crtc_dpll(crtc); > > WARN_ON(!pll->funcs.get_hw_state(dev_priv, pll, > &pipe_config->dpll_hw_state)); > @@ -10458,82 +10427,6 @@ static int haswell_crtc_compute_clock(struct intel_crtc *crtc, > return 0; > } > > -static void bxt_get_ddi_pll(struct drm_i915_private *dev_priv, > - enum port port, > - struct intel_crtc_state *pipe_config) > -{ > - enum intel_dpll_id id; > - > - switch (port) { > - case PORT_A: > - id = DPLL_ID_SKL_DPLL0; > - break; > - case PORT_B: > - id = DPLL_ID_SKL_DPLL1; > - break; > - case PORT_C: > - id = DPLL_ID_SKL_DPLL2; > - break; > - default: > - DRM_ERROR("Incorrect port type\n"); > - return; > - } > - > - pipe_config->shared_dpll = intel_get_shared_dpll_by_id(dev_priv, id); > -} > - > -static void skylake_get_ddi_pll(struct drm_i915_private *dev_priv, > - enum port port, > - struct intel_crtc_state *pipe_config) > -{ > - enum intel_dpll_id id; > - u32 temp; > - > - temp = I915_READ(DPLL_CTRL2) & DPLL_CTRL2_DDI_CLK_SEL_MASK(port); > - id = temp >> (port * 3 + 1); > - > - if (WARN_ON(id < SKL_DPLL0 || id > SKL_DPLL3)) > - return; > - > - pipe_config->shared_dpll = intel_get_shared_dpll_by_id(dev_priv, id); > -} > - > -static void haswell_get_ddi_pll(struct drm_i915_private *dev_priv, > - enum port port, > - struct intel_crtc_state *pipe_config) > -{ > - enum intel_dpll_id id; > - uint32_t ddi_pll_sel = I915_READ(PORT_CLK_SEL(port)); > - > - switch (ddi_pll_sel) { > - case PORT_CLK_SEL_WRPLL1: > - id = DPLL_ID_WRPLL1; > - break; > - case PORT_CLK_SEL_WRPLL2: > - id = DPLL_ID_WRPLL2; > - break; > - 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(ddi_pll_sel); > - /* fall through */ > - case PORT_CLK_SEL_NONE: > - return; > - } > - > - pipe_config->shared_dpll = intel_get_shared_dpll_by_id(dev_priv, id); > -} > - > static bool hsw_get_transcoder_state(struct intel_crtc *crtc, > struct intel_crtc_state *pipe_config, > unsigned long *power_domain_mask) > @@ -10638,6 +10531,7 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc, > { > struct drm_device *dev = crtc->base.dev; > struct drm_i915_private *dev_priv = to_i915(dev); > + struct intel_encoder *encoder; > struct intel_shared_dpll *pll; > enum port port; > uint32_t tmp; > @@ -10646,14 +10540,8 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc, > > port = (tmp & TRANS_DDI_PORT_MASK) >> TRANS_DDI_PORT_SHIFT; > > - if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) > - skylake_get_ddi_pll(dev_priv, port, pipe_config); > - else if (IS_BROXTON(dev)) > - bxt_get_ddi_pll(dev_priv, port, pipe_config); > - else > - haswell_get_ddi_pll(dev_priv, port, pipe_config); > - > - pll = pipe_config->shared_dpll; > + encoder = intel_ddi_get_port_encoder(dev_priv, port); > + pipe_config->shared_dpll = pll = intel_get_encoder_dpll(encoder); > if (pll) { > WARN_ON(!pll->funcs.get_hw_state(dev_priv, pll, > &pipe_config->dpll_hw_state)); > diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c > index 3ffbd69..cb097fb 100644 > --- a/drivers/gpu/drm/i915/intel_dp_mst.c > +++ b/drivers/gpu/drm/i915/intel_dp_mst.c > @@ -150,8 +150,8 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder, > DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links); > > if (intel_dp->active_mst_links == 0) { > - intel_ddi_clk_select(&intel_dig_port->base, > - pipe_config->shared_dpll); > + intel_dpll_map_to_encoder(pipe_config->shared_dpll, > + &intel_dig_port->base); > > intel_prepare_dp_ddi_buffers(&intel_dig_port->base); > intel_dp_set_link_params(intel_dp, > diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c > index 9b02d9c..532236d 100644 > --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c > +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c > @@ -40,6 +40,12 @@ > * Changes to the users are first staged in the atomic state, and then made > * effective by calling intel_shared_dpll_swap_state() during the atomic > * commit phase. > + * > + * The functions intel_dpll_map_to_crtc(), intel_dpll_map_to_encoder(), > + * intel_get_crtc_dpll() and intel_get_encoder_dpll() allows the mapping of > + * dplls to crtcs and encoders to be queried and changed. Whether plls map > + * to encoders or crtcs depends on the platform. The caller needs to know > + * which of the functions to use. > */ > > struct intel_shared_dpll * > @@ -447,6 +453,54 @@ ibx_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, > return pll; > } > > +static struct intel_shared_dpll * > +ibx_get_crtc_dpll(struct intel_crtc *crtc) > +{ > + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); > + enum intel_dpll_id pll_id; > + u32 tmp; > + > + if (HAS_PCH_IBX(dev_priv)) { > + /* > + * The pipe->pch transcoder and pch transcoder->pll > + * mapping is fixed. > + */ > + pll_id = (enum intel_dpll_id) crtc->pipe; > + } else { > + tmp = I915_READ(PCH_DPLL_SEL); > + if (tmp & TRANS_DPLLB_SEL(crtc->pipe)) > + pll_id = DPLL_ID_PCH_PLL_B; > + else > + pll_id= DPLL_ID_PCH_PLL_A; > + } > + > + return intel_get_shared_dpll_by_id(dev_priv, pll_id); > +} > + > +static void > +ibx_dpll_map_to_crtc(struct intel_shared_dpll *dpll, struct intel_crtc *crtc) > +{ > + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); > + enum pipe pipe = crtc->pipe; > + u32 temp, sel; > + > + if (!HAS_PCH_CPT(dev_priv)) > + return; > + > + temp = I915_READ(PCH_DPLL_SEL); > + if (dpll) { > + temp |= TRANS_DPLL_ENABLE(pipe); > + sel = TRANS_DPLLB_SEL(pipe); > + if (dpll->id == DPLL_ID_PCH_PLL_B) > + temp |= sel; > + else > + temp &= ~sel; > + } else { > + temp &= ~(TRANS_DPLL_ENABLE(pipe) | TRANS_DPLLB_SEL(pipe)); > + } > + I915_WRITE(PCH_DPLL_SEL, temp); > +} > + > static void ibx_dump_hw_state(struct drm_i915_private *dev_priv, > struct intel_dpll_hw_state *hw_state) > { > @@ -844,6 +898,73 @@ hsw_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, > return pll; > } > > +static enum intel_dpll_id hsw_reg_to_pll_id(uint32_t ddi_pll_sel) > +{ > + switch (ddi_pll_sel) { > + case PORT_CLK_SEL_WRPLL1: > + return DPLL_ID_WRPLL1; > + case PORT_CLK_SEL_WRPLL2: > + return DPLL_ID_WRPLL2; > + case PORT_CLK_SEL_SPLL: > + return DPLL_ID_SPLL; > + case PORT_CLK_SEL_LCPLL_810: > + return DPLL_ID_LCPLL_810; > + case PORT_CLK_SEL_LCPLL_1350: > + return DPLL_ID_LCPLL_1350; > + case PORT_CLK_SEL_LCPLL_2700: > + return DPLL_ID_LCPLL_2700; > + default: > + MISSING_CASE(ddi_pll_sel); > + /* fall through */ > + case PORT_CLK_SEL_NONE: > + return DPLL_ID_PRIVATE; > + } > +} > + > +static uint32_t hsw_pll_id_to_reg(enum intel_dpll_id id) > +{ > + switch (id) { > + case DPLL_ID_WRPLL1: > + return PORT_CLK_SEL_WRPLL1; > + case DPLL_ID_WRPLL2: > + 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: > + MISSING_CASE(id); > + /* fall through */ > + case DPLL_ID_PRIVATE: > + return PORT_CLK_SEL_NONE; > + } > +} > + > +static struct intel_shared_dpll * > +hsw_get_encoder_dpll(struct intel_encoder *encoder) > +{ > + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); > + enum port port = intel_ddi_get_encoder_port(encoder); > + uint32_t ddi_pll_sel = I915_READ(PORT_CLK_SEL(port)); > + > + return intel_get_shared_dpll_by_id(dev_priv, > + hsw_reg_to_pll_id(ddi_pll_sel)); > +} > + > +static void > +hsw_dpll_map_to_encoder(struct intel_shared_dpll *dpll, > + struct intel_encoder *encoder) > +{ > + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); > + enum port port = intel_ddi_get_encoder_port(encoder); > + > + I915_WRITE(PORT_CLK_SEL(port), hsw_pll_id_to_reg(dpll->id)); > +} > + > static void hsw_dump_hw_state(struct drm_i915_private *dev_priv, > struct intel_dpll_hw_state *hw_state) > { > @@ -1406,6 +1527,41 @@ skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, > return pll; > } > > +static struct intel_shared_dpll * > +skl_get_encoder_dpll(struct intel_encoder *encoder) > +{ > + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); > + enum port port = intel_ddi_get_encoder_port(encoder); > + enum intel_dpll_id id; > + u32 temp; > + > + temp = I915_READ(DPLL_CTRL2) & DPLL_CTRL2_DDI_CLK_SEL_MASK(port); > + id = temp >> (port * 3 + 1); > + > + if (WARN_ON(id < SKL_DPLL0 || id > SKL_DPLL3)) > + return NULL; > + > + return intel_get_shared_dpll_by_id(dev_priv, id); > +} > + > +static void > +skl_dpll_map_to_encoder(struct intel_shared_dpll *dpll, > + struct intel_encoder *encoder) > +{ > + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); > + enum port port = intel_ddi_get_encoder_port(encoder); > + uint32_t val; > + > + val = I915_READ(DPLL_CTRL2); > + > + val &= ~(DPLL_CTRL2_DDI_CLK_OFF(port) | > + DPLL_CTRL2_DDI_CLK_SEL_MASK(port)); > + val |= (DPLL_CTRL2_DDI_CLK_SEL(dpll->id, port) | > + DPLL_CTRL2_DDI_SEL_OVERRIDE(port)); > + > + I915_WRITE(DPLL_CTRL2, val); > +} > + > static void skl_dump_hw_state(struct drm_i915_private *dev_priv, > struct intel_dpll_hw_state *hw_state) > { > @@ -1812,6 +1968,38 @@ bxt_get_dpll(struct intel_crtc *crtc, > > return pll; > } > +static struct intel_shared_dpll * > +bxt_get_encoder_dpll(struct intel_encoder *encoder) > +{ > + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); > + enum port port = intel_ddi_get_encoder_port(encoder); > + enum intel_dpll_id id; > + > + switch (port) { > + case PORT_A: > + id = DPLL_ID_SKL_DPLL0; > + break; > + case PORT_B: > + id = DPLL_ID_SKL_DPLL1; > + break; > + case PORT_C: > + id = DPLL_ID_SKL_DPLL2; > + break; > + default: > + DRM_ERROR("Incorrect port type\n"); > + return NULL; > + } > + > + return intel_get_shared_dpll_by_id(dev_priv, id); > +} > + > +static void > +bxt_dpll_map_to_encoder(struct intel_shared_dpll *dpll, > + struct intel_encoder *encoder) > +{ > + /* Fixed mapping, nothing to do */ > +} > + > > static void bxt_dump_hw_state(struct drm_i915_private *dev_priv, > struct intel_dpll_hw_state *hw_state) > @@ -1859,6 +2047,33 @@ static void intel_ddi_pll_init(struct drm_device *dev) > } > } > > +static void > +noop_dpll_map_to_crtc(struct intel_shared_dpll *dpll, struct intel_crtc *crtc) > +{ > + WARN(1, "Platform does not support mapping DPLLs to CRTCs."); > +} > + > +static struct intel_shared_dpll * > +noop_get_crtc_dpll(struct intel_crtc *crtc) > +{ > + WARN(1, "Platform does not support mapping DPLLs to CRTCs."); > + return NULL; > +} > + > +static void > +noop_dpll_map_to_encoder(struct intel_shared_dpll *dpll, struct intel_encoder *encoder) > +{ > + WARN(1, "Platform does not support mapping DPLLs to encoders."); > +} > + > +static struct intel_shared_dpll * > +noop_get_encoder_dpll(struct intel_encoder *encoder) > +{ > + WARN(1, "Platform does not support mapping DPLLs to encoders."); > + return NULL; > +} > + > + > struct dpll_info { > const char *name; > const int id; > @@ -1873,6 +2088,14 @@ struct intel_dpll_mgr { > struct intel_crtc_state *crtc_state, > struct intel_encoder *encoder); > > + struct intel_shared_dpll *(*get_crtc_dpll)(struct intel_crtc *crtc); > + struct intel_shared_dpll *(*get_encoder_dpll)(struct intel_encoder *encoder); > + > + void (*map_to_crtc)(struct intel_shared_dpll *dpll, > + struct intel_crtc *crtc); > + void (*map_to_encoder)(struct intel_shared_dpll *dpll, > + struct intel_encoder *encoder); > + > void (*dump_hw_state)(struct drm_i915_private *dev_priv, > struct intel_dpll_hw_state *hw_state); > }; > @@ -1886,6 +2109,10 @@ static const struct dpll_info pch_plls[] = { > static const struct intel_dpll_mgr pch_pll_mgr = { > .dpll_info = pch_plls, > .get_dpll = ibx_get_dpll, > + .get_crtc_dpll = ibx_get_crtc_dpll, > + .map_to_crtc = ibx_dpll_map_to_crtc, > + .get_encoder_dpll = noop_get_encoder_dpll, > + .map_to_encoder = noop_dpll_map_to_encoder, > .dump_hw_state = ibx_dump_hw_state, > }; > > @@ -1902,6 +2129,10 @@ static const struct dpll_info hsw_plls[] = { > static const struct intel_dpll_mgr hsw_pll_mgr = { > .dpll_info = hsw_plls, > .get_dpll = hsw_get_dpll, > + .get_crtc_dpll = noop_get_crtc_dpll, > + .map_to_crtc = noop_dpll_map_to_crtc, > + .get_encoder_dpll = hsw_get_encoder_dpll, > + .map_to_encoder = hsw_dpll_map_to_encoder, > .dump_hw_state = hsw_dump_hw_state, > }; > > @@ -1916,6 +2147,10 @@ static const struct dpll_info skl_plls[] = { > static const struct intel_dpll_mgr skl_pll_mgr = { > .dpll_info = skl_plls, > .get_dpll = skl_get_dpll, > + .get_crtc_dpll = noop_get_crtc_dpll, > + .map_to_crtc = noop_dpll_map_to_crtc, > + .get_encoder_dpll = skl_get_encoder_dpll, > + .map_to_encoder = skl_dpll_map_to_encoder, > .dump_hw_state = skl_dump_hw_state, > }; > > @@ -1929,6 +2164,10 @@ static const struct dpll_info bxt_plls[] = { > static const struct intel_dpll_mgr bxt_pll_mgr = { > .dpll_info = bxt_plls, > .get_dpll = bxt_get_dpll, > + .get_crtc_dpll = noop_get_crtc_dpll, > + .map_to_crtc = noop_dpll_map_to_crtc, > + .get_encoder_dpll = bxt_get_encoder_dpll, > + .map_to_encoder = bxt_dpll_map_to_encoder, > .dump_hw_state = bxt_dump_hw_state, > }; > > @@ -2031,6 +2270,66 @@ void intel_release_shared_dpll(struct intel_shared_dpll *dpll, > } > > /** > + * intel_get_crtc_dpll - Get which pll is mapped to a pipe > + * @crtc: pipe > + * > + * Returns the DPLL is mapped to @crtc. NULL indicates no DPLL is mapped to > + * @crtc. > + */ > +struct intel_shared_dpll *intel_get_crtc_dpll(struct intel_crtc *crtc) > +{ > + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); > + > + return dev_priv->dpll_mgr->get_crtc_dpll(crtc); > +} > + > +/** > + * intel_get_encoder_dpll - Get which pll is mapped to an encoder > + * @encoder: encoder > + * > + * Returns the DPLL is mapped to @encoder. NULL indicates no DPLL is mapped to > + * @encoder. > + */ > +struct intel_shared_dpll *intel_get_encoder_dpll(struct intel_encoder *encoder) > +{ > + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); > + > + return dev_priv->dpll_mgr->get_encoder_dpll(encoder); > +} > + > +/** > + * intel_dpll_map_to_crtc - Map DPLL to pipe > + * @dpll: dpll to map > + * @crtc: pipe to map the @dpll to > + * > + * For platforms where DPLLs are mapped to crtcs, program the appropriate > + * bits so that @dpll is mapped to @crtc. > + */ > +void intel_dpll_map_to_crtc(struct intel_shared_dpll *dpll, > + struct intel_crtc *crtc) > +{ > + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); > + > + dev_priv->dpll_mgr->map_to_crtc(dpll, crtc); > +} > + > +/** > + * intel_dpll_map_to_encoder - Map DPLL to encoder > + * @dpll: dpll to map > + * @encoder: encoder to map the @dpll to > + * > + * For platforms where DPLLs are mapped to encoders, program the appropriate > + * bits so that @dpll is mapped to @encoder. > + */ > +void intel_dpll_map_to_encoder(struct intel_shared_dpll *dpll, > + struct intel_encoder *encoder) > +{ > + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); > + > + dev_priv->dpll_mgr->map_to_encoder(dpll, encoder); > +} > + > +/** > * intel_shared_dpll_dump_hw_state - write hw_state to dmesg > * @dev_priv: i915 drm device > * @hw_state: hw state to be written to the log > diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.h b/drivers/gpu/drm/i915/intel_dpll_mgr.h > index 76111a4..7b46c88 100644 > --- a/drivers/gpu/drm/i915/intel_dpll_mgr.h > +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.h > @@ -280,6 +280,13 @@ void intel_disable_shared_dpll(struct intel_crtc *crtc); > void intel_shared_dpll_swap_state(struct drm_atomic_state *state); > void intel_shared_dpll_init(struct drm_device *dev); > > +struct intel_shared_dpll *intel_get_crtc_dpll(struct intel_crtc *crtc); > +struct intel_shared_dpll *intel_get_encoder_dpll(struct intel_encoder *encoder); > +void intel_dpll_map_to_crtc(struct intel_shared_dpll *dpll, > + struct intel_crtc *crtc); > +void intel_dpll_map_to_encoder(struct intel_shared_dpll *dpll, > + struct intel_encoder *encoder); > + > void intel_dpll_dump_hw_state(struct drm_i915_private *dev_priv, > struct intel_dpll_hw_state *hw_state); > > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h > index 7874f66..a04d917 100644 > --- a/drivers/gpu/drm/i915/intel_drv.h > +++ b/drivers/gpu/drm/i915/intel_drv.h > @@ -1136,8 +1136,6 @@ void intel_crt_init(struct drm_device *dev); > void intel_crt_reset(struct drm_encoder *encoder); > > /* intel_ddi.c */ > -void intel_ddi_clk_select(struct intel_encoder *encoder, > - struct intel_shared_dpll *pll); > void intel_ddi_fdi_post_disable(struct intel_encoder *intel_encoder, > struct intel_crtc_state *old_crtc_state, > struct drm_connector_state *old_conn_state); > @@ -1145,6 +1143,8 @@ void intel_prepare_dp_ddi_buffers(struct intel_encoder *encoder); > void hsw_fdi_link_train(struct drm_crtc *crtc); > void intel_ddi_init(struct drm_device *dev, enum port port); > enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder); > +struct intel_encoder * > +intel_ddi_get_port_encoder(struct drm_i915_private *dev_priv, enum port port); > bool intel_ddi_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe); > void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc); > void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv, > -- > 2.5.5 > > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/intel-gfx
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 4077205..144fe5c 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -319,6 +319,19 @@ enum port intel_ddi_get_encoder_port(struct intel_encoder *encoder) } } +struct intel_encoder * +intel_ddi_get_port_encoder(struct drm_i915_private *dev_priv, enum port port) +{ + struct intel_encoder *encoder; + + for_each_intel_encoder(&dev_priv->drm, encoder) { + if (port == intel_ddi_get_encoder_port(encoder)) + return encoder; + } + + return NULL; +} + static const struct ddi_buf_trans * bdw_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries) { @@ -582,11 +595,12 @@ void hsw_fdi_link_train(struct drm_crtc *crtc) struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_encoder *encoder; - u32 temp, i, rx_ctl_val, ddi_pll_sel; + u32 temp, i, rx_ctl_val; for_each_encoder_on_crtc(dev, crtc, encoder) { WARN_ON(encoder->type != INTEL_OUTPUT_ANALOG); intel_prepare_dp_ddi_buffers(encoder); + break; } /* Set the FDI_RX_MISC pwrdn lanes and the 2 workarounds listed at the @@ -613,9 +627,7 @@ void hsw_fdi_link_train(struct drm_crtc *crtc) I915_WRITE(FDI_RX_CTL(PIPE_A), rx_ctl_val); /* Configure Port Clock Select */ - ddi_pll_sel = hsw_pll_to_ddi_pll_sel(intel_crtc->config->shared_dpll); - I915_WRITE(PORT_CLK_SEL(PORT_E), ddi_pll_sel); - WARN_ON(ddi_pll_sel != PORT_CLK_SEL_SPLL); + intel_dpll_map_to_encoder(intel_crtc->config->shared_dpll, encoder); /* Start the training iterating through available voltages and emphasis, * testing each value twice. */ @@ -1607,33 +1619,6 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp) return DDI_BUF_TRANS_SELECT(level); } -void intel_ddi_clk_select(struct intel_encoder *encoder, - struct intel_shared_dpll *pll) -{ - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - enum port port = intel_ddi_get_encoder_port(encoder); - - if (WARN_ON(!pll)) - return; - - if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { - uint32_t val; - - /* DDI -> PLL mapping */ - val = I915_READ(DPLL_CTRL2); - - val &= ~(DPLL_CTRL2_DDI_CLK_OFF(port) | - DPLL_CTRL2_DDI_CLK_SEL_MASK(port)); - val |= (DPLL_CTRL2_DDI_CLK_SEL(pll->id, port) | - DPLL_CTRL2_DDI_SEL_OVERRIDE(port)); - - I915_WRITE(DPLL_CTRL2, val); - - } else if (INTEL_INFO(dev_priv)->gen < 9) { - I915_WRITE(PORT_CLK_SEL(port), hsw_pll_to_ddi_pll_sel(pll)); - } -} - static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder, int link_rate, uint32_t lane_count, struct intel_shared_dpll *pll, @@ -1648,7 +1633,7 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder, if (encoder->type == INTEL_OUTPUT_EDP) intel_edp_panel_on(intel_dp); - intel_ddi_clk_select(encoder, pll); + intel_dpll_map_to_encoder(pll, encoder); intel_prepare_dp_ddi_buffers(encoder); intel_ddi_init_dp_buf_reg(encoder); intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); @@ -1669,7 +1654,7 @@ static void intel_ddi_pre_enable_hdmi(struct intel_encoder *encoder, int level = intel_ddi_hdmi_level(dev_priv, port); intel_dp_dual_mode_set_tmds_output(intel_hdmi, true); - intel_ddi_clk_select(encoder, pll); + intel_dpll_map_to_encoder(pll, encoder); intel_prepare_hdmi_ddi_buffers(encoder); if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) skl_ddi_set_iboost(encoder, level); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8ecaf18..22e3c46 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4555,19 +4555,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) /* We need to program the right clock selection before writing the pixel * mutliplier into the DPLL. */ - if (HAS_PCH_CPT(dev)) { - u32 sel; - - temp = I915_READ(PCH_DPLL_SEL); - temp |= TRANS_DPLL_ENABLE(pipe); - sel = TRANS_DPLLB_SEL(pipe); - if (intel_crtc->config->shared_dpll == - intel_get_shared_dpll_by_id(dev_priv, DPLL_ID_PCH_PLL_B)) - temp |= sel; - else - temp &= ~sel; - I915_WRITE(PCH_DPLL_SEL, temp); - } + intel_dpll_map_to_crtc(intel_crtc->config->shared_dpll, intel_crtc); /* XXX: pch pll's can be enabled any time before we enable the PCH * transcoder, and we actually should do this to not upset any PCH @@ -5574,9 +5562,7 @@ static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state, I915_WRITE(reg, temp); /* disable DPLL_SEL */ - temp = I915_READ(PCH_DPLL_SEL); - temp &= ~(TRANS_DPLL_ENABLE(pipe) | TRANS_DPLLB_SEL(pipe)); - I915_WRITE(PCH_DPLL_SEL, temp); + intel_dpll_map_to_crtc(NULL, intel_crtc); } ironlake_fdi_pll_disable(intel_crtc); @@ -9952,7 +9938,6 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc, if (I915_READ(PCH_TRANSCONF(crtc->pipe)) & TRANS_ENABLE) { struct intel_shared_dpll *pll; - enum intel_dpll_id pll_id; pipe_config->has_pch_encoder = true; @@ -9962,23 +9947,7 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc, ironlake_get_fdi_m_n_config(crtc, pipe_config); - if (HAS_PCH_IBX(dev_priv)) { - /* - * The pipe->pch transcoder and pch transcoder->pll - * mapping is fixed. - */ - pll_id = (enum intel_dpll_id) crtc->pipe; - } else { - tmp = I915_READ(PCH_DPLL_SEL); - if (tmp & TRANS_DPLLB_SEL(crtc->pipe)) - pll_id = DPLL_ID_PCH_PLL_B; - else - pll_id= DPLL_ID_PCH_PLL_A; - } - - pipe_config->shared_dpll = - intel_get_shared_dpll_by_id(dev_priv, pll_id); - pll = pipe_config->shared_dpll; + pipe_config->shared_dpll = pll = intel_get_crtc_dpll(crtc); WARN_ON(!pll->funcs.get_hw_state(dev_priv, pll, &pipe_config->dpll_hw_state)); @@ -10458,82 +10427,6 @@ static int haswell_crtc_compute_clock(struct intel_crtc *crtc, return 0; } -static void bxt_get_ddi_pll(struct drm_i915_private *dev_priv, - enum port port, - struct intel_crtc_state *pipe_config) -{ - enum intel_dpll_id id; - - switch (port) { - case PORT_A: - id = DPLL_ID_SKL_DPLL0; - break; - case PORT_B: - id = DPLL_ID_SKL_DPLL1; - break; - case PORT_C: - id = DPLL_ID_SKL_DPLL2; - break; - default: - DRM_ERROR("Incorrect port type\n"); - return; - } - - pipe_config->shared_dpll = intel_get_shared_dpll_by_id(dev_priv, id); -} - -static void skylake_get_ddi_pll(struct drm_i915_private *dev_priv, - enum port port, - struct intel_crtc_state *pipe_config) -{ - enum intel_dpll_id id; - u32 temp; - - temp = I915_READ(DPLL_CTRL2) & DPLL_CTRL2_DDI_CLK_SEL_MASK(port); - id = temp >> (port * 3 + 1); - - if (WARN_ON(id < SKL_DPLL0 || id > SKL_DPLL3)) - return; - - pipe_config->shared_dpll = intel_get_shared_dpll_by_id(dev_priv, id); -} - -static void haswell_get_ddi_pll(struct drm_i915_private *dev_priv, - enum port port, - struct intel_crtc_state *pipe_config) -{ - enum intel_dpll_id id; - uint32_t ddi_pll_sel = I915_READ(PORT_CLK_SEL(port)); - - switch (ddi_pll_sel) { - case PORT_CLK_SEL_WRPLL1: - id = DPLL_ID_WRPLL1; - break; - case PORT_CLK_SEL_WRPLL2: - id = DPLL_ID_WRPLL2; - break; - 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(ddi_pll_sel); - /* fall through */ - case PORT_CLK_SEL_NONE: - return; - } - - pipe_config->shared_dpll = intel_get_shared_dpll_by_id(dev_priv, id); -} - static bool hsw_get_transcoder_state(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config, unsigned long *power_domain_mask) @@ -10638,6 +10531,7 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc, { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_encoder *encoder; struct intel_shared_dpll *pll; enum port port; uint32_t tmp; @@ -10646,14 +10540,8 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc, port = (tmp & TRANS_DDI_PORT_MASK) >> TRANS_DDI_PORT_SHIFT; - if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) - skylake_get_ddi_pll(dev_priv, port, pipe_config); - else if (IS_BROXTON(dev)) - bxt_get_ddi_pll(dev_priv, port, pipe_config); - else - haswell_get_ddi_pll(dev_priv, port, pipe_config); - - pll = pipe_config->shared_dpll; + encoder = intel_ddi_get_port_encoder(dev_priv, port); + pipe_config->shared_dpll = pll = intel_get_encoder_dpll(encoder); if (pll) { WARN_ON(!pll->funcs.get_hw_state(dev_priv, pll, &pipe_config->dpll_hw_state)); diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 3ffbd69..cb097fb 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -150,8 +150,8 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder, DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links); if (intel_dp->active_mst_links == 0) { - intel_ddi_clk_select(&intel_dig_port->base, - pipe_config->shared_dpll); + intel_dpll_map_to_encoder(pipe_config->shared_dpll, + &intel_dig_port->base); intel_prepare_dp_ddi_buffers(&intel_dig_port->base); intel_dp_set_link_params(intel_dp, diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index 9b02d9c..532236d 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -40,6 +40,12 @@ * Changes to the users are first staged in the atomic state, and then made * effective by calling intel_shared_dpll_swap_state() during the atomic * commit phase. + * + * The functions intel_dpll_map_to_crtc(), intel_dpll_map_to_encoder(), + * intel_get_crtc_dpll() and intel_get_encoder_dpll() allows the mapping of + * dplls to crtcs and encoders to be queried and changed. Whether plls map + * to encoders or crtcs depends on the platform. The caller needs to know + * which of the functions to use. */ struct intel_shared_dpll * @@ -447,6 +453,54 @@ ibx_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, return pll; } +static struct intel_shared_dpll * +ibx_get_crtc_dpll(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum intel_dpll_id pll_id; + u32 tmp; + + if (HAS_PCH_IBX(dev_priv)) { + /* + * The pipe->pch transcoder and pch transcoder->pll + * mapping is fixed. + */ + pll_id = (enum intel_dpll_id) crtc->pipe; + } else { + tmp = I915_READ(PCH_DPLL_SEL); + if (tmp & TRANS_DPLLB_SEL(crtc->pipe)) + pll_id = DPLL_ID_PCH_PLL_B; + else + pll_id= DPLL_ID_PCH_PLL_A; + } + + return intel_get_shared_dpll_by_id(dev_priv, pll_id); +} + +static void +ibx_dpll_map_to_crtc(struct intel_shared_dpll *dpll, struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum pipe pipe = crtc->pipe; + u32 temp, sel; + + if (!HAS_PCH_CPT(dev_priv)) + return; + + temp = I915_READ(PCH_DPLL_SEL); + if (dpll) { + temp |= TRANS_DPLL_ENABLE(pipe); + sel = TRANS_DPLLB_SEL(pipe); + if (dpll->id == DPLL_ID_PCH_PLL_B) + temp |= sel; + else + temp &= ~sel; + } else { + temp &= ~(TRANS_DPLL_ENABLE(pipe) | TRANS_DPLLB_SEL(pipe)); + } + I915_WRITE(PCH_DPLL_SEL, temp); +} + static void ibx_dump_hw_state(struct drm_i915_private *dev_priv, struct intel_dpll_hw_state *hw_state) { @@ -844,6 +898,73 @@ hsw_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, return pll; } +static enum intel_dpll_id hsw_reg_to_pll_id(uint32_t ddi_pll_sel) +{ + switch (ddi_pll_sel) { + case PORT_CLK_SEL_WRPLL1: + return DPLL_ID_WRPLL1; + case PORT_CLK_SEL_WRPLL2: + return DPLL_ID_WRPLL2; + case PORT_CLK_SEL_SPLL: + return DPLL_ID_SPLL; + case PORT_CLK_SEL_LCPLL_810: + return DPLL_ID_LCPLL_810; + case PORT_CLK_SEL_LCPLL_1350: + return DPLL_ID_LCPLL_1350; + case PORT_CLK_SEL_LCPLL_2700: + return DPLL_ID_LCPLL_2700; + default: + MISSING_CASE(ddi_pll_sel); + /* fall through */ + case PORT_CLK_SEL_NONE: + return DPLL_ID_PRIVATE; + } +} + +static uint32_t hsw_pll_id_to_reg(enum intel_dpll_id id) +{ + switch (id) { + case DPLL_ID_WRPLL1: + return PORT_CLK_SEL_WRPLL1; + case DPLL_ID_WRPLL2: + 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: + MISSING_CASE(id); + /* fall through */ + case DPLL_ID_PRIVATE: + return PORT_CLK_SEL_NONE; + } +} + +static struct intel_shared_dpll * +hsw_get_encoder_dpll(struct intel_encoder *encoder) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + enum port port = intel_ddi_get_encoder_port(encoder); + uint32_t ddi_pll_sel = I915_READ(PORT_CLK_SEL(port)); + + return intel_get_shared_dpll_by_id(dev_priv, + hsw_reg_to_pll_id(ddi_pll_sel)); +} + +static void +hsw_dpll_map_to_encoder(struct intel_shared_dpll *dpll, + struct intel_encoder *encoder) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + enum port port = intel_ddi_get_encoder_port(encoder); + + I915_WRITE(PORT_CLK_SEL(port), hsw_pll_id_to_reg(dpll->id)); +} + static void hsw_dump_hw_state(struct drm_i915_private *dev_priv, struct intel_dpll_hw_state *hw_state) { @@ -1406,6 +1527,41 @@ skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, return pll; } +static struct intel_shared_dpll * +skl_get_encoder_dpll(struct intel_encoder *encoder) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + enum port port = intel_ddi_get_encoder_port(encoder); + enum intel_dpll_id id; + u32 temp; + + temp = I915_READ(DPLL_CTRL2) & DPLL_CTRL2_DDI_CLK_SEL_MASK(port); + id = temp >> (port * 3 + 1); + + if (WARN_ON(id < SKL_DPLL0 || id > SKL_DPLL3)) + return NULL; + + return intel_get_shared_dpll_by_id(dev_priv, id); +} + +static void +skl_dpll_map_to_encoder(struct intel_shared_dpll *dpll, + struct intel_encoder *encoder) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + enum port port = intel_ddi_get_encoder_port(encoder); + uint32_t val; + + val = I915_READ(DPLL_CTRL2); + + val &= ~(DPLL_CTRL2_DDI_CLK_OFF(port) | + DPLL_CTRL2_DDI_CLK_SEL_MASK(port)); + val |= (DPLL_CTRL2_DDI_CLK_SEL(dpll->id, port) | + DPLL_CTRL2_DDI_SEL_OVERRIDE(port)); + + I915_WRITE(DPLL_CTRL2, val); +} + static void skl_dump_hw_state(struct drm_i915_private *dev_priv, struct intel_dpll_hw_state *hw_state) { @@ -1812,6 +1968,38 @@ bxt_get_dpll(struct intel_crtc *crtc, return pll; } +static struct intel_shared_dpll * +bxt_get_encoder_dpll(struct intel_encoder *encoder) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + enum port port = intel_ddi_get_encoder_port(encoder); + enum intel_dpll_id id; + + switch (port) { + case PORT_A: + id = DPLL_ID_SKL_DPLL0; + break; + case PORT_B: + id = DPLL_ID_SKL_DPLL1; + break; + case PORT_C: + id = DPLL_ID_SKL_DPLL2; + break; + default: + DRM_ERROR("Incorrect port type\n"); + return NULL; + } + + return intel_get_shared_dpll_by_id(dev_priv, id); +} + +static void +bxt_dpll_map_to_encoder(struct intel_shared_dpll *dpll, + struct intel_encoder *encoder) +{ + /* Fixed mapping, nothing to do */ +} + static void bxt_dump_hw_state(struct drm_i915_private *dev_priv, struct intel_dpll_hw_state *hw_state) @@ -1859,6 +2047,33 @@ static void intel_ddi_pll_init(struct drm_device *dev) } } +static void +noop_dpll_map_to_crtc(struct intel_shared_dpll *dpll, struct intel_crtc *crtc) +{ + WARN(1, "Platform does not support mapping DPLLs to CRTCs."); +} + +static struct intel_shared_dpll * +noop_get_crtc_dpll(struct intel_crtc *crtc) +{ + WARN(1, "Platform does not support mapping DPLLs to CRTCs."); + return NULL; +} + +static void +noop_dpll_map_to_encoder(struct intel_shared_dpll *dpll, struct intel_encoder *encoder) +{ + WARN(1, "Platform does not support mapping DPLLs to encoders."); +} + +static struct intel_shared_dpll * +noop_get_encoder_dpll(struct intel_encoder *encoder) +{ + WARN(1, "Platform does not support mapping DPLLs to encoders."); + return NULL; +} + + struct dpll_info { const char *name; const int id; @@ -1873,6 +2088,14 @@ struct intel_dpll_mgr { struct intel_crtc_state *crtc_state, struct intel_encoder *encoder); + struct intel_shared_dpll *(*get_crtc_dpll)(struct intel_crtc *crtc); + struct intel_shared_dpll *(*get_encoder_dpll)(struct intel_encoder *encoder); + + void (*map_to_crtc)(struct intel_shared_dpll *dpll, + struct intel_crtc *crtc); + void (*map_to_encoder)(struct intel_shared_dpll *dpll, + struct intel_encoder *encoder); + void (*dump_hw_state)(struct drm_i915_private *dev_priv, struct intel_dpll_hw_state *hw_state); }; @@ -1886,6 +2109,10 @@ static const struct dpll_info pch_plls[] = { static const struct intel_dpll_mgr pch_pll_mgr = { .dpll_info = pch_plls, .get_dpll = ibx_get_dpll, + .get_crtc_dpll = ibx_get_crtc_dpll, + .map_to_crtc = ibx_dpll_map_to_crtc, + .get_encoder_dpll = noop_get_encoder_dpll, + .map_to_encoder = noop_dpll_map_to_encoder, .dump_hw_state = ibx_dump_hw_state, }; @@ -1902,6 +2129,10 @@ static const struct dpll_info hsw_plls[] = { static const struct intel_dpll_mgr hsw_pll_mgr = { .dpll_info = hsw_plls, .get_dpll = hsw_get_dpll, + .get_crtc_dpll = noop_get_crtc_dpll, + .map_to_crtc = noop_dpll_map_to_crtc, + .get_encoder_dpll = hsw_get_encoder_dpll, + .map_to_encoder = hsw_dpll_map_to_encoder, .dump_hw_state = hsw_dump_hw_state, }; @@ -1916,6 +2147,10 @@ static const struct dpll_info skl_plls[] = { static const struct intel_dpll_mgr skl_pll_mgr = { .dpll_info = skl_plls, .get_dpll = skl_get_dpll, + .get_crtc_dpll = noop_get_crtc_dpll, + .map_to_crtc = noop_dpll_map_to_crtc, + .get_encoder_dpll = skl_get_encoder_dpll, + .map_to_encoder = skl_dpll_map_to_encoder, .dump_hw_state = skl_dump_hw_state, }; @@ -1929,6 +2164,10 @@ static const struct dpll_info bxt_plls[] = { static const struct intel_dpll_mgr bxt_pll_mgr = { .dpll_info = bxt_plls, .get_dpll = bxt_get_dpll, + .get_crtc_dpll = noop_get_crtc_dpll, + .map_to_crtc = noop_dpll_map_to_crtc, + .get_encoder_dpll = bxt_get_encoder_dpll, + .map_to_encoder = bxt_dpll_map_to_encoder, .dump_hw_state = bxt_dump_hw_state, }; @@ -2031,6 +2270,66 @@ void intel_release_shared_dpll(struct intel_shared_dpll *dpll, } /** + * intel_get_crtc_dpll - Get which pll is mapped to a pipe + * @crtc: pipe + * + * Returns the DPLL is mapped to @crtc. NULL indicates no DPLL is mapped to + * @crtc. + */ +struct intel_shared_dpll *intel_get_crtc_dpll(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + + return dev_priv->dpll_mgr->get_crtc_dpll(crtc); +} + +/** + * intel_get_encoder_dpll - Get which pll is mapped to an encoder + * @encoder: encoder + * + * Returns the DPLL is mapped to @encoder. NULL indicates no DPLL is mapped to + * @encoder. + */ +struct intel_shared_dpll *intel_get_encoder_dpll(struct intel_encoder *encoder) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + + return dev_priv->dpll_mgr->get_encoder_dpll(encoder); +} + +/** + * intel_dpll_map_to_crtc - Map DPLL to pipe + * @dpll: dpll to map + * @crtc: pipe to map the @dpll to + * + * For platforms where DPLLs are mapped to crtcs, program the appropriate + * bits so that @dpll is mapped to @crtc. + */ +void intel_dpll_map_to_crtc(struct intel_shared_dpll *dpll, + struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + + dev_priv->dpll_mgr->map_to_crtc(dpll, crtc); +} + +/** + * intel_dpll_map_to_encoder - Map DPLL to encoder + * @dpll: dpll to map + * @encoder: encoder to map the @dpll to + * + * For platforms where DPLLs are mapped to encoders, program the appropriate + * bits so that @dpll is mapped to @encoder. + */ +void intel_dpll_map_to_encoder(struct intel_shared_dpll *dpll, + struct intel_encoder *encoder) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + + dev_priv->dpll_mgr->map_to_encoder(dpll, encoder); +} + +/** * intel_shared_dpll_dump_hw_state - write hw_state to dmesg * @dev_priv: i915 drm device * @hw_state: hw state to be written to the log diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.h b/drivers/gpu/drm/i915/intel_dpll_mgr.h index 76111a4..7b46c88 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.h @@ -280,6 +280,13 @@ void intel_disable_shared_dpll(struct intel_crtc *crtc); void intel_shared_dpll_swap_state(struct drm_atomic_state *state); void intel_shared_dpll_init(struct drm_device *dev); +struct intel_shared_dpll *intel_get_crtc_dpll(struct intel_crtc *crtc); +struct intel_shared_dpll *intel_get_encoder_dpll(struct intel_encoder *encoder); +void intel_dpll_map_to_crtc(struct intel_shared_dpll *dpll, + struct intel_crtc *crtc); +void intel_dpll_map_to_encoder(struct intel_shared_dpll *dpll, + struct intel_encoder *encoder); + void intel_dpll_dump_hw_state(struct drm_i915_private *dev_priv, struct intel_dpll_hw_state *hw_state); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 7874f66..a04d917 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1136,8 +1136,6 @@ void intel_crt_init(struct drm_device *dev); void intel_crt_reset(struct drm_encoder *encoder); /* intel_ddi.c */ -void intel_ddi_clk_select(struct intel_encoder *encoder, - struct intel_shared_dpll *pll); void intel_ddi_fdi_post_disable(struct intel_encoder *intel_encoder, struct intel_crtc_state *old_crtc_state, struct drm_connector_state *old_conn_state); @@ -1145,6 +1143,8 @@ void intel_prepare_dp_ddi_buffers(struct intel_encoder *encoder); void hsw_fdi_link_train(struct drm_crtc *crtc); void intel_ddi_init(struct drm_device *dev, enum port port); enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder); +struct intel_encoder * +intel_ddi_get_port_encoder(struct drm_i915_private *dev_priv, enum port port); bool intel_ddi_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe); void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc); void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv,
Abstract the platform specific bits of mapping the dplls under a platform independ entrypoints so the differences between platforms are contained in the dpll code. I.e., it removes IS_PLATFORM() macros from other parts of the code. Signed-off-by: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com> --- drivers/gpu/drm/i915/intel_ddi.c | 51 ++---- drivers/gpu/drm/i915/intel_display.c | 124 +------------- drivers/gpu/drm/i915/intel_dp_mst.c | 4 +- drivers/gpu/drm/i915/intel_dpll_mgr.c | 299 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_dpll_mgr.h | 7 + drivers/gpu/drm/i915/intel_drv.h | 4 +- 6 files changed, 334 insertions(+), 155 deletions(-)