drm/i915: migrate pll enable/disable code to intel_dpll.[ch]
This moves the older i9xx/vlv/chv enable/disable to dpll file. Signed-off-by: Dave Airlie <airlied@redhat.com> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/7fa8c76b0f07f3ede9efd7c1f989f33fbc8c53a3.1612536383.git.jani.nikula@intel.com
This commit is contained in:
parent
92ae3db4c1
commit
12edd6ab14
@ -113,10 +113,6 @@ static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state);
|
||||
static void ilk_set_pipeconf(const struct intel_crtc_state *crtc_state);
|
||||
static void hsw_set_pipeconf(const struct intel_crtc_state *crtc_state);
|
||||
static void bdw_set_pipemisc(const struct intel_crtc_state *crtc_state);
|
||||
static void vlv_prepare_pll(struct intel_crtc *crtc,
|
||||
const struct intel_crtc_state *pipe_config);
|
||||
static void chv_prepare_pll(struct intel_crtc *crtc,
|
||||
const struct intel_crtc_state *pipe_config);
|
||||
static void ilk_pfit_enable(const struct intel_crtc_state *crtc_state);
|
||||
static void intel_modeset_setup_hw_state(struct drm_device *dev,
|
||||
struct drm_modeset_acquire_ctx *ctx);
|
||||
@ -569,224 +565,6 @@ static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv,
|
||||
assert_pch_hdmi_disabled(dev_priv, pipe, PORT_D, PCH_HDMID);
|
||||
}
|
||||
|
||||
static void _vlv_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;
|
||||
|
||||
intel_de_write(dev_priv, DPLL(pipe), pipe_config->dpll_hw_state.dpll);
|
||||
intel_de_posting_read(dev_priv, DPLL(pipe));
|
||||
udelay(150);
|
||||
|
||||
if (intel_de_wait_for_set(dev_priv, DPLL(pipe), DPLL_LOCK_VLV, 1))
|
||||
drm_err(&dev_priv->drm, "DPLL %d failed to lock\n", pipe);
|
||||
}
|
||||
|
||||
static void vlv_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;
|
||||
|
||||
assert_pipe_disabled(dev_priv, pipe_config->cpu_transcoder);
|
||||
|
||||
/* 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)
|
||||
_vlv_enable_pll(crtc, pipe_config);
|
||||
|
||||
intel_de_write(dev_priv, DPLL_MD(pipe),
|
||||
pipe_config->dpll_hw_state.dpll_md);
|
||||
intel_de_posting_read(dev_priv, DPLL_MD(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;
|
||||
enum dpio_channel port = vlv_pipe_to_channel(pipe);
|
||||
u32 tmp;
|
||||
|
||||
vlv_dpio_get(dev_priv);
|
||||
|
||||
/* Enable back the 10bit clock to display controller */
|
||||
tmp = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW14(port));
|
||||
tmp |= DPIO_DCLKP_EN;
|
||||
vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW14(port), tmp);
|
||||
|
||||
vlv_dpio_put(dev_priv);
|
||||
|
||||
/*
|
||||
* Need to wait > 100ns between dclkp clock enable bit and PLL enable.
|
||||
*/
|
||||
udelay(1);
|
||||
|
||||
/* Enable PLL */
|
||||
intel_de_write(dev_priv, DPLL(pipe), pipe_config->dpll_hw_state.dpll);
|
||||
|
||||
/* Check PLL is locked */
|
||||
if (intel_de_wait_for_set(dev_priv, DPLL(pipe), DPLL_LOCK_VLV, 1))
|
||||
drm_err(&dev_priv->drm, "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;
|
||||
|
||||
assert_pipe_disabled(dev_priv, pipe_config->cpu_transcoder);
|
||||
|
||||
/* 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);
|
||||
|
||||
if (pipe != PIPE_A) {
|
||||
/*
|
||||
* WaPixelRepeatModeFixForC0:chv
|
||||
*
|
||||
* DPLLCMD is AWOL. Use chicken bits to propagate
|
||||
* the value from DPLLBMD to either pipe B or C.
|
||||
*/
|
||||
intel_de_write(dev_priv, CBR4_VLV, CBR_DPLLBMD_PIPE(pipe));
|
||||
intel_de_write(dev_priv, DPLL_MD(PIPE_B),
|
||||
pipe_config->dpll_hw_state.dpll_md);
|
||||
intel_de_write(dev_priv, CBR4_VLV, 0);
|
||||
dev_priv->chv_dpll_md[pipe] = pipe_config->dpll_hw_state.dpll_md;
|
||||
|
||||
/*
|
||||
* DPLLB VGA mode also seems to cause problems.
|
||||
* We should always have it disabled.
|
||||
*/
|
||||
drm_WARN_ON(&dev_priv->drm,
|
||||
(intel_de_read(dev_priv, DPLL(PIPE_B)) &
|
||||
DPLL_VGA_MODE_DIS) == 0);
|
||||
} else {
|
||||
intel_de_write(dev_priv, DPLL_MD(pipe),
|
||||
pipe_config->dpll_hw_state.dpll_md);
|
||||
intel_de_posting_read(dev_priv, DPLL_MD(pipe));
|
||||
}
|
||||
}
|
||||
|
||||
static bool i9xx_has_pps(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
if (IS_I830(dev_priv))
|
||||
return false;
|
||||
|
||||
return IS_PINEVIEW(dev_priv) || IS_MOBILE(dev_priv);
|
||||
}
|
||||
|
||||
static void i9xx_enable_pll(struct intel_crtc *crtc,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
i915_reg_t reg = DPLL(crtc->pipe);
|
||||
u32 dpll = crtc_state->dpll_hw_state.dpll;
|
||||
int i;
|
||||
|
||||
assert_pipe_disabled(dev_priv, crtc_state->cpu_transcoder);
|
||||
|
||||
/* PLL is protected by panel, make sure we can write it */
|
||||
if (i9xx_has_pps(dev_priv))
|
||||
assert_panel_unlocked(dev_priv, crtc->pipe);
|
||||
|
||||
/*
|
||||
* Apparently we need to have VGA mode enabled prior to changing
|
||||
* the P1/P2 dividers. Otherwise the DPLL will keep using the old
|
||||
* dividers, even though the register value does change.
|
||||
*/
|
||||
intel_de_write(dev_priv, reg, dpll & ~DPLL_VGA_MODE_DIS);
|
||||
intel_de_write(dev_priv, reg, dpll);
|
||||
|
||||
/* Wait for the clocks to stabilize. */
|
||||
intel_de_posting_read(dev_priv, reg);
|
||||
udelay(150);
|
||||
|
||||
if (INTEL_GEN(dev_priv) >= 4) {
|
||||
intel_de_write(dev_priv, DPLL_MD(crtc->pipe),
|
||||
crtc_state->dpll_hw_state.dpll_md);
|
||||
} else {
|
||||
/* The pixel multiplier can only be updated once the
|
||||
* DPLL is enabled and the clocks are stable.
|
||||
*
|
||||
* So write it again.
|
||||
*/
|
||||
intel_de_write(dev_priv, reg, dpll);
|
||||
}
|
||||
|
||||
/* We do this three times for luck */
|
||||
for (i = 0; i < 3; i++) {
|
||||
intel_de_write(dev_priv, reg, dpll);
|
||||
intel_de_posting_read(dev_priv, reg);
|
||||
udelay(150); /* wait for warmup */
|
||||
}
|
||||
}
|
||||
|
||||
static void i9xx_disable_pll(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
|
||||
/* Don't disable pipe or pipe PLLs if needed */
|
||||
if (IS_I830(dev_priv))
|
||||
return;
|
||||
|
||||
/* Make sure the pipe isn't still relying on us */
|
||||
assert_pipe_disabled(dev_priv, crtc_state->cpu_transcoder);
|
||||
|
||||
intel_de_write(dev_priv, DPLL(pipe), DPLL_VGA_MODE_DIS);
|
||||
intel_de_posting_read(dev_priv, DPLL(pipe));
|
||||
}
|
||||
|
||||
static void vlv_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, (enum transcoder)pipe);
|
||||
|
||||
val = DPLL_INTEGRATED_REF_CLK_VLV |
|
||||
DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS;
|
||||
if (pipe != PIPE_A)
|
||||
val |= DPLL_INTEGRATED_CRI_CLK_VLV;
|
||||
|
||||
intel_de_write(dev_priv, DPLL(pipe), val);
|
||||
intel_de_posting_read(dev_priv, DPLL(pipe));
|
||||
}
|
||||
|
||||
static void chv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
|
||||
{
|
||||
enum dpio_channel port = vlv_pipe_to_channel(pipe);
|
||||
u32 val;
|
||||
|
||||
/* Make sure the pipe isn't still relying on us */
|
||||
assert_pipe_disabled(dev_priv, (enum transcoder)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;
|
||||
|
||||
intel_de_write(dev_priv, DPLL(pipe), val);
|
||||
intel_de_posting_read(dev_priv, DPLL(pipe));
|
||||
|
||||
vlv_dpio_get(dev_priv);
|
||||
|
||||
/* Disable 10bit clock to display controller */
|
||||
val = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW14(port));
|
||||
val &= ~DPIO_DCLKP_EN;
|
||||
vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW14(port), val);
|
||||
|
||||
vlv_dpio_put(dev_priv);
|
||||
}
|
||||
|
||||
void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
|
||||
struct intel_digital_port *dig_port,
|
||||
unsigned int expected_mask)
|
||||
@ -5774,35 +5552,6 @@ static void intel_panel_sanitize_ssc(struct drm_i915_private *dev_priv)
|
||||
}
|
||||
}
|
||||
|
||||
static void vlv_pllb_recal_opamp(struct drm_i915_private *dev_priv, enum pipe
|
||||
pipe)
|
||||
{
|
||||
u32 reg_val;
|
||||
|
||||
/*
|
||||
* PLLB opamp always calibrates to max value of 0x3f, force enable it
|
||||
* and set it to a reasonable value instead.
|
||||
*/
|
||||
reg_val = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW9(1));
|
||||
reg_val &= 0xffffff00;
|
||||
reg_val |= 0x00000030;
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW9(1), reg_val);
|
||||
|
||||
reg_val = vlv_dpio_read(dev_priv, pipe, VLV_REF_DW13);
|
||||
reg_val &= 0x00ffffff;
|
||||
reg_val |= 0x8c000000;
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_REF_DW13, reg_val);
|
||||
|
||||
reg_val = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW9(1));
|
||||
reg_val &= 0xffffff00;
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW9(1), reg_val);
|
||||
|
||||
reg_val = vlv_dpio_read(dev_priv, pipe, VLV_REF_DW13);
|
||||
reg_val &= 0x00ffffff;
|
||||
reg_val |= 0xb0000000;
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_REF_DW13, reg_val);
|
||||
}
|
||||
|
||||
static void intel_pch_transcoder_set_m_n(const struct intel_crtc_state *crtc_state,
|
||||
const struct intel_link_m_n *m_n)
|
||||
{
|
||||
@ -5898,267 +5647,6 @@ void intel_dp_set_m_n(const struct intel_crtc_state *crtc_state, enum link_m_n_s
|
||||
intel_cpu_transcoder_set_m_n(crtc_state, dp_m_n, dp_m2_n2);
|
||||
}
|
||||
|
||||
static void vlv_prepare_pll(struct intel_crtc *crtc,
|
||||
const struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
struct drm_device *dev = crtc->base.dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
u32 mdiv;
|
||||
u32 bestn, bestm1, bestm2, bestp1, bestp2;
|
||||
u32 coreclk, reg_val;
|
||||
|
||||
/* Enable Refclk */
|
||||
intel_de_write(dev_priv, DPLL(pipe),
|
||||
pipe_config->dpll_hw_state.dpll & ~(DPLL_VCO_ENABLE | DPLL_EXT_BUFFER_ENABLE_VLV));
|
||||
|
||||
/* No need to actually set up the DPLL with DSI */
|
||||
if ((pipe_config->dpll_hw_state.dpll & DPLL_VCO_ENABLE) == 0)
|
||||
return;
|
||||
|
||||
vlv_dpio_get(dev_priv);
|
||||
|
||||
bestn = pipe_config->dpll.n;
|
||||
bestm1 = pipe_config->dpll.m1;
|
||||
bestm2 = pipe_config->dpll.m2;
|
||||
bestp1 = pipe_config->dpll.p1;
|
||||
bestp2 = pipe_config->dpll.p2;
|
||||
|
||||
/* See eDP HDMI DPIO driver vbios notes doc */
|
||||
|
||||
/* PLL B needs special handling */
|
||||
if (pipe == PIPE_B)
|
||||
vlv_pllb_recal_opamp(dev_priv, pipe);
|
||||
|
||||
/* Set up Tx target for periodic Rcomp update */
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW9_BCAST, 0x0100000f);
|
||||
|
||||
/* Disable target IRef on PLL */
|
||||
reg_val = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW8(pipe));
|
||||
reg_val &= 0x00ffffff;
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW8(pipe), reg_val);
|
||||
|
||||
/* Disable fast lock */
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_CMN_DW0, 0x610);
|
||||
|
||||
/* Set idtafcrecal before PLL is enabled */
|
||||
mdiv = ((bestm1 << DPIO_M1DIV_SHIFT) | (bestm2 & DPIO_M2DIV_MASK));
|
||||
mdiv |= ((bestp1 << DPIO_P1_SHIFT) | (bestp2 << DPIO_P2_SHIFT));
|
||||
mdiv |= ((bestn << DPIO_N_SHIFT));
|
||||
mdiv |= (1 << DPIO_K_SHIFT);
|
||||
|
||||
/*
|
||||
* Post divider depends on pixel clock rate, DAC vs digital (and LVDS,
|
||||
* but we don't support that).
|
||||
* Note: don't use the DAC post divider as it seems unstable.
|
||||
*/
|
||||
mdiv |= (DPIO_POST_DIV_HDMIDP << DPIO_POST_DIV_SHIFT);
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW3(pipe), mdiv);
|
||||
|
||||
mdiv |= DPIO_ENABLE_CALIBRATION;
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW3(pipe), mdiv);
|
||||
|
||||
/* Set HBR and RBR LPF coefficients */
|
||||
if (pipe_config->port_clock == 162000 ||
|
||||
intel_crtc_has_type(pipe_config, INTEL_OUTPUT_ANALOG) ||
|
||||
intel_crtc_has_type(pipe_config, INTEL_OUTPUT_HDMI))
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW10(pipe),
|
||||
0x009f0003);
|
||||
else
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW10(pipe),
|
||||
0x00d0000f);
|
||||
|
||||
if (intel_crtc_has_dp_encoder(pipe_config)) {
|
||||
/* Use SSC source */
|
||||
if (pipe == PIPE_A)
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe),
|
||||
0x0df40000);
|
||||
else
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe),
|
||||
0x0df70000);
|
||||
} else { /* HDMI or VGA */
|
||||
/* Use bend source */
|
||||
if (pipe == PIPE_A)
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe),
|
||||
0x0df70000);
|
||||
else
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe),
|
||||
0x0df40000);
|
||||
}
|
||||
|
||||
coreclk = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW7(pipe));
|
||||
coreclk = (coreclk & 0x0000ff00) | 0x01c00000;
|
||||
if (intel_crtc_has_dp_encoder(pipe_config))
|
||||
coreclk |= 0x01000000;
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW7(pipe), coreclk);
|
||||
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW11(pipe), 0x87871000);
|
||||
|
||||
vlv_dpio_put(dev_priv);
|
||||
}
|
||||
|
||||
static void chv_prepare_pll(struct intel_crtc *crtc,
|
||||
const struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
struct drm_device *dev = crtc->base.dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
enum dpio_channel port = vlv_pipe_to_channel(pipe);
|
||||
u32 loopfilter, tribuf_calcntr;
|
||||
u32 bestn, bestm1, bestm2, bestp1, bestp2, bestm2_frac;
|
||||
u32 dpio_val;
|
||||
int vco;
|
||||
|
||||
/* Enable Refclk and SSC */
|
||||
intel_de_write(dev_priv, 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)
|
||||
return;
|
||||
|
||||
bestn = pipe_config->dpll.n;
|
||||
bestm2_frac = pipe_config->dpll.m2 & 0x3fffff;
|
||||
bestm1 = pipe_config->dpll.m1;
|
||||
bestm2 = pipe_config->dpll.m2 >> 22;
|
||||
bestp1 = pipe_config->dpll.p1;
|
||||
bestp2 = pipe_config->dpll.p2;
|
||||
vco = pipe_config->dpll.vco;
|
||||
dpio_val = 0;
|
||||
loopfilter = 0;
|
||||
|
||||
vlv_dpio_get(dev_priv);
|
||||
|
||||
/* p1 and p2 divider */
|
||||
vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW13(port),
|
||||
5 << DPIO_CHV_S1_DIV_SHIFT |
|
||||
bestp1 << DPIO_CHV_P1_DIV_SHIFT |
|
||||
bestp2 << DPIO_CHV_P2_DIV_SHIFT |
|
||||
1 << DPIO_CHV_K_DIV_SHIFT);
|
||||
|
||||
/* Feedback post-divider - m2 */
|
||||
vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW0(port), bestm2);
|
||||
|
||||
/* Feedback refclk divider - n and m1 */
|
||||
vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW1(port),
|
||||
DPIO_CHV_M1_DIV_BY_2 |
|
||||
1 << DPIO_CHV_N_DIV_SHIFT);
|
||||
|
||||
/* M2 fraction division */
|
||||
vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW2(port), bestm2_frac);
|
||||
|
||||
/* M2 fraction division enable */
|
||||
dpio_val = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW3(port));
|
||||
dpio_val &= ~(DPIO_CHV_FEEDFWD_GAIN_MASK | DPIO_CHV_FRAC_DIV_EN);
|
||||
dpio_val |= (2 << DPIO_CHV_FEEDFWD_GAIN_SHIFT);
|
||||
if (bestm2_frac)
|
||||
dpio_val |= DPIO_CHV_FRAC_DIV_EN;
|
||||
vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW3(port), dpio_val);
|
||||
|
||||
/* Program digital lock detect threshold */
|
||||
dpio_val = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW9(port));
|
||||
dpio_val &= ~(DPIO_CHV_INT_LOCK_THRESHOLD_MASK |
|
||||
DPIO_CHV_INT_LOCK_THRESHOLD_SEL_COARSE);
|
||||
dpio_val |= (0x5 << DPIO_CHV_INT_LOCK_THRESHOLD_SHIFT);
|
||||
if (!bestm2_frac)
|
||||
dpio_val |= DPIO_CHV_INT_LOCK_THRESHOLD_SEL_COARSE;
|
||||
vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW9(port), dpio_val);
|
||||
|
||||
/* Loop filter */
|
||||
if (vco == 5400000) {
|
||||
loopfilter |= (0x3 << DPIO_CHV_PROP_COEFF_SHIFT);
|
||||
loopfilter |= (0x8 << DPIO_CHV_INT_COEFF_SHIFT);
|
||||
loopfilter |= (0x1 << DPIO_CHV_GAIN_CTRL_SHIFT);
|
||||
tribuf_calcntr = 0x9;
|
||||
} else if (vco <= 6200000) {
|
||||
loopfilter |= (0x5 << DPIO_CHV_PROP_COEFF_SHIFT);
|
||||
loopfilter |= (0xB << DPIO_CHV_INT_COEFF_SHIFT);
|
||||
loopfilter |= (0x3 << DPIO_CHV_GAIN_CTRL_SHIFT);
|
||||
tribuf_calcntr = 0x9;
|
||||
} else if (vco <= 6480000) {
|
||||
loopfilter |= (0x4 << DPIO_CHV_PROP_COEFF_SHIFT);
|
||||
loopfilter |= (0x9 << DPIO_CHV_INT_COEFF_SHIFT);
|
||||
loopfilter |= (0x3 << DPIO_CHV_GAIN_CTRL_SHIFT);
|
||||
tribuf_calcntr = 0x8;
|
||||
} else {
|
||||
/* Not supported. Apply the same limits as in the max case */
|
||||
loopfilter |= (0x4 << DPIO_CHV_PROP_COEFF_SHIFT);
|
||||
loopfilter |= (0x9 << DPIO_CHV_INT_COEFF_SHIFT);
|
||||
loopfilter |= (0x3 << DPIO_CHV_GAIN_CTRL_SHIFT);
|
||||
tribuf_calcntr = 0;
|
||||
}
|
||||
vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW6(port), loopfilter);
|
||||
|
||||
dpio_val = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW8(port));
|
||||
dpio_val &= ~DPIO_CHV_TDC_TARGET_CNT_MASK;
|
||||
dpio_val |= (tribuf_calcntr << DPIO_CHV_TDC_TARGET_CNT_SHIFT);
|
||||
vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW8(port), dpio_val);
|
||||
|
||||
/* AFC Recal */
|
||||
vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW14(port),
|
||||
vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW14(port)) |
|
||||
DPIO_AFC_RECAL);
|
||||
|
||||
vlv_dpio_put(dev_priv);
|
||||
}
|
||||
|
||||
/**
|
||||
* vlv_force_pll_on - forcibly enable just the PLL
|
||||
* @dev_priv: i915 private structure
|
||||
* @pipe: pipe PLL to enable
|
||||
* @dpll: PLL configuration
|
||||
*
|
||||
* Enable the PLL for @pipe using the supplied @dpll config. To be used
|
||||
* in cases where we need the PLL enabled even when @pipe is not going to
|
||||
* be enabled.
|
||||
*/
|
||||
int vlv_force_pll_on(struct drm_i915_private *dev_priv, enum pipe pipe,
|
||||
const struct dpll *dpll)
|
||||
{
|
||||
struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
|
||||
struct intel_crtc_state *pipe_config;
|
||||
|
||||
pipe_config = intel_crtc_state_alloc(crtc);
|
||||
if (!pipe_config)
|
||||
return -ENOMEM;
|
||||
|
||||
pipe_config->cpu_transcoder = (enum transcoder)pipe;
|
||||
pipe_config->pixel_multiplier = 1;
|
||||
pipe_config->dpll = *dpll;
|
||||
|
||||
if (IS_CHERRYVIEW(dev_priv)) {
|
||||
chv_compute_dpll(crtc, pipe_config);
|
||||
chv_prepare_pll(crtc, pipe_config);
|
||||
chv_enable_pll(crtc, pipe_config);
|
||||
} else {
|
||||
vlv_compute_dpll(crtc, pipe_config);
|
||||
vlv_prepare_pll(crtc, pipe_config);
|
||||
vlv_enable_pll(crtc, pipe_config);
|
||||
}
|
||||
|
||||
kfree(pipe_config);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* vlv_force_pll_off - forcibly disable just the PLL
|
||||
* @dev_priv: i915 private structure
|
||||
* @pipe: pipe PLL to disable
|
||||
*
|
||||
* Disable the PLL for @pipe. To be used in cases where we need
|
||||
* the PLL enabled even when @pipe is not going to be enabled.
|
||||
*/
|
||||
void vlv_force_pll_off(struct drm_i915_private *dev_priv, enum pipe pipe)
|
||||
{
|
||||
if (IS_CHERRYVIEW(dev_priv))
|
||||
chv_disable_pll(dev_priv, pipe);
|
||||
else
|
||||
vlv_disable_pll(dev_priv, pipe);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void intel_set_transcoder_timings(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
|
@ -594,9 +594,6 @@ void intel_cleanup_plane_fb(struct drm_plane *plane,
|
||||
void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv,
|
||||
enum pipe pipe);
|
||||
|
||||
int vlv_force_pll_on(struct drm_i915_private *dev_priv, enum pipe pipe,
|
||||
const struct dpll *dpll);
|
||||
void vlv_force_pll_off(struct drm_i915_private *dev_priv, enum pipe pipe);
|
||||
int lpt_get_iclkip(struct drm_i915_private *dev_priv);
|
||||
bool intel_fuzzy_clock_check(int clock1, int clock2);
|
||||
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "intel_dp_aux.h"
|
||||
#include "intel_dp_link_training.h"
|
||||
#include "intel_dp_mst.h"
|
||||
#include "intel_dpll.h"
|
||||
#include "intel_dpio_phy.h"
|
||||
#include "intel_fifo_underrun.h"
|
||||
#include "intel_hdcp.h"
|
||||
|
@ -3,11 +3,13 @@
|
||||
* Copyright © 2020 Intel Corporation
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include "intel_crtc.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_display.h"
|
||||
#include "intel_dpll.h"
|
||||
#include "intel_lvds.h"
|
||||
#include "intel_panel.h"
|
||||
#include "intel_sideband.h"
|
||||
|
||||
struct intel_limit {
|
||||
struct {
|
||||
@ -1361,3 +1363,510 @@ intel_dpll_init_clock_hook(struct drm_i915_private *dev_priv)
|
||||
else
|
||||
dev_priv->display.crtc_compute_clock = i8xx_crtc_compute_clock;
|
||||
}
|
||||
|
||||
static bool i9xx_has_pps(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
if (IS_I830(dev_priv))
|
||||
return false;
|
||||
|
||||
return IS_PINEVIEW(dev_priv) || IS_MOBILE(dev_priv);
|
||||
}
|
||||
|
||||
void i9xx_enable_pll(struct intel_crtc *crtc,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
i915_reg_t reg = DPLL(crtc->pipe);
|
||||
u32 dpll = crtc_state->dpll_hw_state.dpll;
|
||||
int i;
|
||||
|
||||
assert_pipe_disabled(dev_priv, crtc_state->cpu_transcoder);
|
||||
|
||||
/* PLL is protected by panel, make sure we can write it */
|
||||
if (i9xx_has_pps(dev_priv))
|
||||
assert_panel_unlocked(dev_priv, crtc->pipe);
|
||||
|
||||
/*
|
||||
* Apparently we need to have VGA mode enabled prior to changing
|
||||
* the P1/P2 dividers. Otherwise the DPLL will keep using the old
|
||||
* dividers, even though the register value does change.
|
||||
*/
|
||||
intel_de_write(dev_priv, reg, dpll & ~DPLL_VGA_MODE_DIS);
|
||||
intel_de_write(dev_priv, reg, dpll);
|
||||
|
||||
/* Wait for the clocks to stabilize. */
|
||||
intel_de_posting_read(dev_priv, reg);
|
||||
udelay(150);
|
||||
|
||||
if (INTEL_GEN(dev_priv) >= 4) {
|
||||
intel_de_write(dev_priv, DPLL_MD(crtc->pipe),
|
||||
crtc_state->dpll_hw_state.dpll_md);
|
||||
} else {
|
||||
/* The pixel multiplier can only be updated once the
|
||||
* DPLL is enabled and the clocks are stable.
|
||||
*
|
||||
* So write it again.
|
||||
*/
|
||||
intel_de_write(dev_priv, reg, dpll);
|
||||
}
|
||||
|
||||
/* We do this three times for luck */
|
||||
for (i = 0; i < 3; i++) {
|
||||
intel_de_write(dev_priv, reg, dpll);
|
||||
intel_de_posting_read(dev_priv, reg);
|
||||
udelay(150); /* wait for warmup */
|
||||
}
|
||||
}
|
||||
|
||||
static void vlv_pllb_recal_opamp(struct drm_i915_private *dev_priv,
|
||||
enum pipe pipe)
|
||||
{
|
||||
u32 reg_val;
|
||||
|
||||
/*
|
||||
* PLLB opamp always calibrates to max value of 0x3f, force enable it
|
||||
* and set it to a reasonable value instead.
|
||||
*/
|
||||
reg_val = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW9(1));
|
||||
reg_val &= 0xffffff00;
|
||||
reg_val |= 0x00000030;
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW9(1), reg_val);
|
||||
|
||||
reg_val = vlv_dpio_read(dev_priv, pipe, VLV_REF_DW13);
|
||||
reg_val &= 0x00ffffff;
|
||||
reg_val |= 0x8c000000;
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_REF_DW13, reg_val);
|
||||
|
||||
reg_val = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW9(1));
|
||||
reg_val &= 0xffffff00;
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW9(1), reg_val);
|
||||
|
||||
reg_val = vlv_dpio_read(dev_priv, pipe, VLV_REF_DW13);
|
||||
reg_val &= 0x00ffffff;
|
||||
reg_val |= 0xb0000000;
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_REF_DW13, reg_val);
|
||||
}
|
||||
|
||||
static void _vlv_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;
|
||||
|
||||
intel_de_write(dev_priv, DPLL(pipe), pipe_config->dpll_hw_state.dpll);
|
||||
intel_de_posting_read(dev_priv, DPLL(pipe));
|
||||
udelay(150);
|
||||
|
||||
if (intel_de_wait_for_set(dev_priv, DPLL(pipe), DPLL_LOCK_VLV, 1))
|
||||
drm_err(&dev_priv->drm, "DPLL %d failed to lock\n", pipe);
|
||||
}
|
||||
|
||||
void vlv_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;
|
||||
|
||||
assert_pipe_disabled(dev_priv, pipe_config->cpu_transcoder);
|
||||
|
||||
/* 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)
|
||||
_vlv_enable_pll(crtc, pipe_config);
|
||||
|
||||
intel_de_write(dev_priv, DPLL_MD(pipe),
|
||||
pipe_config->dpll_hw_state.dpll_md);
|
||||
intel_de_posting_read(dev_priv, DPLL_MD(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;
|
||||
enum dpio_channel port = vlv_pipe_to_channel(pipe);
|
||||
u32 tmp;
|
||||
|
||||
vlv_dpio_get(dev_priv);
|
||||
|
||||
/* Enable back the 10bit clock to display controller */
|
||||
tmp = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW14(port));
|
||||
tmp |= DPIO_DCLKP_EN;
|
||||
vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW14(port), tmp);
|
||||
|
||||
vlv_dpio_put(dev_priv);
|
||||
|
||||
/*
|
||||
* Need to wait > 100ns between dclkp clock enable bit and PLL enable.
|
||||
*/
|
||||
udelay(1);
|
||||
|
||||
/* Enable PLL */
|
||||
intel_de_write(dev_priv, DPLL(pipe), pipe_config->dpll_hw_state.dpll);
|
||||
|
||||
/* Check PLL is locked */
|
||||
if (intel_de_wait_for_set(dev_priv, DPLL(pipe), DPLL_LOCK_VLV, 1))
|
||||
drm_err(&dev_priv->drm, "PLL %d failed to lock\n", pipe);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
assert_pipe_disabled(dev_priv, pipe_config->cpu_transcoder);
|
||||
|
||||
/* 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);
|
||||
|
||||
if (pipe != PIPE_A) {
|
||||
/*
|
||||
* WaPixelRepeatModeFixForC0:chv
|
||||
*
|
||||
* DPLLCMD is AWOL. Use chicken bits to propagate
|
||||
* the value from DPLLBMD to either pipe B or C.
|
||||
*/
|
||||
intel_de_write(dev_priv, CBR4_VLV, CBR_DPLLBMD_PIPE(pipe));
|
||||
intel_de_write(dev_priv, DPLL_MD(PIPE_B),
|
||||
pipe_config->dpll_hw_state.dpll_md);
|
||||
intel_de_write(dev_priv, CBR4_VLV, 0);
|
||||
dev_priv->chv_dpll_md[pipe] = pipe_config->dpll_hw_state.dpll_md;
|
||||
|
||||
/*
|
||||
* DPLLB VGA mode also seems to cause problems.
|
||||
* We should always have it disabled.
|
||||
*/
|
||||
drm_WARN_ON(&dev_priv->drm,
|
||||
(intel_de_read(dev_priv, DPLL(PIPE_B)) &
|
||||
DPLL_VGA_MODE_DIS) == 0);
|
||||
} else {
|
||||
intel_de_write(dev_priv, DPLL_MD(pipe),
|
||||
pipe_config->dpll_hw_state.dpll_md);
|
||||
intel_de_posting_read(dev_priv, DPLL_MD(pipe));
|
||||
}
|
||||
}
|
||||
|
||||
void vlv_prepare_pll(struct intel_crtc *crtc,
|
||||
const struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
struct drm_device *dev = crtc->base.dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
u32 mdiv;
|
||||
u32 bestn, bestm1, bestm2, bestp1, bestp2;
|
||||
u32 coreclk, reg_val;
|
||||
|
||||
/* Enable Refclk */
|
||||
intel_de_write(dev_priv, DPLL(pipe),
|
||||
pipe_config->dpll_hw_state.dpll & ~(DPLL_VCO_ENABLE | DPLL_EXT_BUFFER_ENABLE_VLV));
|
||||
|
||||
/* No need to actually set up the DPLL with DSI */
|
||||
if ((pipe_config->dpll_hw_state.dpll & DPLL_VCO_ENABLE) == 0)
|
||||
return;
|
||||
|
||||
vlv_dpio_get(dev_priv);
|
||||
|
||||
bestn = pipe_config->dpll.n;
|
||||
bestm1 = pipe_config->dpll.m1;
|
||||
bestm2 = pipe_config->dpll.m2;
|
||||
bestp1 = pipe_config->dpll.p1;
|
||||
bestp2 = pipe_config->dpll.p2;
|
||||
|
||||
/* See eDP HDMI DPIO driver vbios notes doc */
|
||||
|
||||
/* PLL B needs special handling */
|
||||
if (pipe == PIPE_B)
|
||||
vlv_pllb_recal_opamp(dev_priv, pipe);
|
||||
|
||||
/* Set up Tx target for periodic Rcomp update */
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW9_BCAST, 0x0100000f);
|
||||
|
||||
/* Disable target IRef on PLL */
|
||||
reg_val = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW8(pipe));
|
||||
reg_val &= 0x00ffffff;
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW8(pipe), reg_val);
|
||||
|
||||
/* Disable fast lock */
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_CMN_DW0, 0x610);
|
||||
|
||||
/* Set idtafcrecal before PLL is enabled */
|
||||
mdiv = ((bestm1 << DPIO_M1DIV_SHIFT) | (bestm2 & DPIO_M2DIV_MASK));
|
||||
mdiv |= ((bestp1 << DPIO_P1_SHIFT) | (bestp2 << DPIO_P2_SHIFT));
|
||||
mdiv |= ((bestn << DPIO_N_SHIFT));
|
||||
mdiv |= (1 << DPIO_K_SHIFT);
|
||||
|
||||
/*
|
||||
* Post divider depends on pixel clock rate, DAC vs digital (and LVDS,
|
||||
* but we don't support that).
|
||||
* Note: don't use the DAC post divider as it seems unstable.
|
||||
*/
|
||||
mdiv |= (DPIO_POST_DIV_HDMIDP << DPIO_POST_DIV_SHIFT);
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW3(pipe), mdiv);
|
||||
|
||||
mdiv |= DPIO_ENABLE_CALIBRATION;
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW3(pipe), mdiv);
|
||||
|
||||
/* Set HBR and RBR LPF coefficients */
|
||||
if (pipe_config->port_clock == 162000 ||
|
||||
intel_crtc_has_type(pipe_config, INTEL_OUTPUT_ANALOG) ||
|
||||
intel_crtc_has_type(pipe_config, INTEL_OUTPUT_HDMI))
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW10(pipe),
|
||||
0x009f0003);
|
||||
else
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW10(pipe),
|
||||
0x00d0000f);
|
||||
|
||||
if (intel_crtc_has_dp_encoder(pipe_config)) {
|
||||
/* Use SSC source */
|
||||
if (pipe == PIPE_A)
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe),
|
||||
0x0df40000);
|
||||
else
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe),
|
||||
0x0df70000);
|
||||
} else { /* HDMI or VGA */
|
||||
/* Use bend source */
|
||||
if (pipe == PIPE_A)
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe),
|
||||
0x0df70000);
|
||||
else
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe),
|
||||
0x0df40000);
|
||||
}
|
||||
|
||||
coreclk = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW7(pipe));
|
||||
coreclk = (coreclk & 0x0000ff00) | 0x01c00000;
|
||||
if (intel_crtc_has_dp_encoder(pipe_config))
|
||||
coreclk |= 0x01000000;
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW7(pipe), coreclk);
|
||||
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW11(pipe), 0x87871000);
|
||||
|
||||
vlv_dpio_put(dev_priv);
|
||||
}
|
||||
|
||||
void chv_prepare_pll(struct intel_crtc *crtc,
|
||||
const struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
struct drm_device *dev = crtc->base.dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
enum dpio_channel port = vlv_pipe_to_channel(pipe);
|
||||
u32 loopfilter, tribuf_calcntr;
|
||||
u32 bestn, bestm1, bestm2, bestp1, bestp2, bestm2_frac;
|
||||
u32 dpio_val;
|
||||
int vco;
|
||||
|
||||
/* Enable Refclk and SSC */
|
||||
intel_de_write(dev_priv, 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)
|
||||
return;
|
||||
|
||||
bestn = pipe_config->dpll.n;
|
||||
bestm2_frac = pipe_config->dpll.m2 & 0x3fffff;
|
||||
bestm1 = pipe_config->dpll.m1;
|
||||
bestm2 = pipe_config->dpll.m2 >> 22;
|
||||
bestp1 = pipe_config->dpll.p1;
|
||||
bestp2 = pipe_config->dpll.p2;
|
||||
vco = pipe_config->dpll.vco;
|
||||
dpio_val = 0;
|
||||
loopfilter = 0;
|
||||
|
||||
vlv_dpio_get(dev_priv);
|
||||
|
||||
/* p1 and p2 divider */
|
||||
vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW13(port),
|
||||
5 << DPIO_CHV_S1_DIV_SHIFT |
|
||||
bestp1 << DPIO_CHV_P1_DIV_SHIFT |
|
||||
bestp2 << DPIO_CHV_P2_DIV_SHIFT |
|
||||
1 << DPIO_CHV_K_DIV_SHIFT);
|
||||
|
||||
/* Feedback post-divider - m2 */
|
||||
vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW0(port), bestm2);
|
||||
|
||||
/* Feedback refclk divider - n and m1 */
|
||||
vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW1(port),
|
||||
DPIO_CHV_M1_DIV_BY_2 |
|
||||
1 << DPIO_CHV_N_DIV_SHIFT);
|
||||
|
||||
/* M2 fraction division */
|
||||
vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW2(port), bestm2_frac);
|
||||
|
||||
/* M2 fraction division enable */
|
||||
dpio_val = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW3(port));
|
||||
dpio_val &= ~(DPIO_CHV_FEEDFWD_GAIN_MASK | DPIO_CHV_FRAC_DIV_EN);
|
||||
dpio_val |= (2 << DPIO_CHV_FEEDFWD_GAIN_SHIFT);
|
||||
if (bestm2_frac)
|
||||
dpio_val |= DPIO_CHV_FRAC_DIV_EN;
|
||||
vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW3(port), dpio_val);
|
||||
|
||||
/* Program digital lock detect threshold */
|
||||
dpio_val = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW9(port));
|
||||
dpio_val &= ~(DPIO_CHV_INT_LOCK_THRESHOLD_MASK |
|
||||
DPIO_CHV_INT_LOCK_THRESHOLD_SEL_COARSE);
|
||||
dpio_val |= (0x5 << DPIO_CHV_INT_LOCK_THRESHOLD_SHIFT);
|
||||
if (!bestm2_frac)
|
||||
dpio_val |= DPIO_CHV_INT_LOCK_THRESHOLD_SEL_COARSE;
|
||||
vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW9(port), dpio_val);
|
||||
|
||||
/* Loop filter */
|
||||
if (vco == 5400000) {
|
||||
loopfilter |= (0x3 << DPIO_CHV_PROP_COEFF_SHIFT);
|
||||
loopfilter |= (0x8 << DPIO_CHV_INT_COEFF_SHIFT);
|
||||
loopfilter |= (0x1 << DPIO_CHV_GAIN_CTRL_SHIFT);
|
||||
tribuf_calcntr = 0x9;
|
||||
} else if (vco <= 6200000) {
|
||||
loopfilter |= (0x5 << DPIO_CHV_PROP_COEFF_SHIFT);
|
||||
loopfilter |= (0xB << DPIO_CHV_INT_COEFF_SHIFT);
|
||||
loopfilter |= (0x3 << DPIO_CHV_GAIN_CTRL_SHIFT);
|
||||
tribuf_calcntr = 0x9;
|
||||
} else if (vco <= 6480000) {
|
||||
loopfilter |= (0x4 << DPIO_CHV_PROP_COEFF_SHIFT);
|
||||
loopfilter |= (0x9 << DPIO_CHV_INT_COEFF_SHIFT);
|
||||
loopfilter |= (0x3 << DPIO_CHV_GAIN_CTRL_SHIFT);
|
||||
tribuf_calcntr = 0x8;
|
||||
} else {
|
||||
/* Not supported. Apply the same limits as in the max case */
|
||||
loopfilter |= (0x4 << DPIO_CHV_PROP_COEFF_SHIFT);
|
||||
loopfilter |= (0x9 << DPIO_CHV_INT_COEFF_SHIFT);
|
||||
loopfilter |= (0x3 << DPIO_CHV_GAIN_CTRL_SHIFT);
|
||||
tribuf_calcntr = 0;
|
||||
}
|
||||
vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW6(port), loopfilter);
|
||||
|
||||
dpio_val = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW8(port));
|
||||
dpio_val &= ~DPIO_CHV_TDC_TARGET_CNT_MASK;
|
||||
dpio_val |= (tribuf_calcntr << DPIO_CHV_TDC_TARGET_CNT_SHIFT);
|
||||
vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW8(port), dpio_val);
|
||||
|
||||
/* AFC Recal */
|
||||
vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW14(port),
|
||||
vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW14(port)) |
|
||||
DPIO_AFC_RECAL);
|
||||
|
||||
vlv_dpio_put(dev_priv);
|
||||
}
|
||||
|
||||
/**
|
||||
* vlv_force_pll_on - forcibly enable just the PLL
|
||||
* @dev_priv: i915 private structure
|
||||
* @pipe: pipe PLL to enable
|
||||
* @dpll: PLL configuration
|
||||
*
|
||||
* Enable the PLL for @pipe using the supplied @dpll config. To be used
|
||||
* in cases where we need the PLL enabled even when @pipe is not going to
|
||||
* be enabled.
|
||||
*/
|
||||
int vlv_force_pll_on(struct drm_i915_private *dev_priv, enum pipe pipe,
|
||||
const struct dpll *dpll)
|
||||
{
|
||||
struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
|
||||
struct intel_crtc_state *pipe_config;
|
||||
|
||||
pipe_config = intel_crtc_state_alloc(crtc);
|
||||
if (!pipe_config)
|
||||
return -ENOMEM;
|
||||
|
||||
pipe_config->cpu_transcoder = (enum transcoder)pipe;
|
||||
pipe_config->pixel_multiplier = 1;
|
||||
pipe_config->dpll = *dpll;
|
||||
|
||||
if (IS_CHERRYVIEW(dev_priv)) {
|
||||
chv_compute_dpll(crtc, pipe_config);
|
||||
chv_prepare_pll(crtc, pipe_config);
|
||||
chv_enable_pll(crtc, pipe_config);
|
||||
} else {
|
||||
vlv_compute_dpll(crtc, pipe_config);
|
||||
vlv_prepare_pll(crtc, pipe_config);
|
||||
vlv_enable_pll(crtc, pipe_config);
|
||||
}
|
||||
|
||||
kfree(pipe_config);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void vlv_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, (enum transcoder)pipe);
|
||||
|
||||
val = DPLL_INTEGRATED_REF_CLK_VLV |
|
||||
DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS;
|
||||
if (pipe != PIPE_A)
|
||||
val |= DPLL_INTEGRATED_CRI_CLK_VLV;
|
||||
|
||||
intel_de_write(dev_priv, DPLL(pipe), val);
|
||||
intel_de_posting_read(dev_priv, DPLL(pipe));
|
||||
}
|
||||
|
||||
void chv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
|
||||
{
|
||||
enum dpio_channel port = vlv_pipe_to_channel(pipe);
|
||||
u32 val;
|
||||
|
||||
/* Make sure the pipe isn't still relying on us */
|
||||
assert_pipe_disabled(dev_priv, (enum transcoder)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;
|
||||
|
||||
intel_de_write(dev_priv, DPLL(pipe), val);
|
||||
intel_de_posting_read(dev_priv, DPLL(pipe));
|
||||
|
||||
vlv_dpio_get(dev_priv);
|
||||
|
||||
/* Disable 10bit clock to display controller */
|
||||
val = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW14(port));
|
||||
val &= ~DPIO_DCLKP_EN;
|
||||
vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW14(port), val);
|
||||
|
||||
vlv_dpio_put(dev_priv);
|
||||
}
|
||||
|
||||
void i9xx_disable_pll(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
|
||||
/* Don't disable pipe or pipe PLLs if needed */
|
||||
if (IS_I830(dev_priv))
|
||||
return;
|
||||
|
||||
/* Make sure the pipe isn't still relying on us */
|
||||
assert_pipe_disabled(dev_priv, crtc_state->cpu_transcoder);
|
||||
|
||||
intel_de_write(dev_priv, DPLL(pipe), DPLL_VGA_MODE_DIS);
|
||||
intel_de_posting_read(dev_priv, DPLL(pipe));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* vlv_force_pll_off - forcibly disable just the PLL
|
||||
* @dev_priv: i915 private structure
|
||||
* @pipe: pipe PLL to disable
|
||||
*
|
||||
* Disable the PLL for @pipe. To be used in cases where we need
|
||||
* the PLL enabled even when @pipe is not going to be enabled.
|
||||
*/
|
||||
void vlv_force_pll_off(struct drm_i915_private *dev_priv, enum pipe pipe)
|
||||
{
|
||||
if (IS_CHERRYVIEW(dev_priv))
|
||||
chv_disable_pll(dev_priv, pipe);
|
||||
else
|
||||
vlv_disable_pll(dev_priv, pipe);
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ struct dpll;
|
||||
struct drm_i915_private;
|
||||
struct intel_crtc;
|
||||
struct intel_crtc_state;
|
||||
enum pipe;
|
||||
|
||||
void intel_dpll_init_clock_hook(struct drm_i915_private *dev_priv);
|
||||
int vlv_calc_dpll_params(int refclk, struct dpll *clock);
|
||||
@ -20,4 +21,21 @@ void vlv_compute_dpll(struct intel_crtc *crtc,
|
||||
void chv_compute_dpll(struct intel_crtc *crtc,
|
||||
struct intel_crtc_state *pipe_config);
|
||||
|
||||
int vlv_force_pll_on(struct drm_i915_private *dev_priv, enum pipe pipe,
|
||||
const struct dpll *dpll);
|
||||
void vlv_force_pll_off(struct drm_i915_private *dev_priv, enum pipe pipe);
|
||||
void i9xx_enable_pll(struct intel_crtc *crtc,
|
||||
const struct intel_crtc_state *crtc_state);
|
||||
void vlv_enable_pll(struct intel_crtc *crtc,
|
||||
const struct intel_crtc_state *pipe_config);
|
||||
void chv_enable_pll(struct intel_crtc *crtc,
|
||||
const struct intel_crtc_state *pipe_config);
|
||||
void vlv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe);
|
||||
void chv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe);
|
||||
void i9xx_disable_pll(const struct intel_crtc_state *crtc_state);
|
||||
void vlv_prepare_pll(struct intel_crtc *crtc,
|
||||
const struct intel_crtc_state *pipe_config);
|
||||
void chv_prepare_pll(struct intel_crtc *crtc,
|
||||
const struct intel_crtc_state *pipe_config);
|
||||
|
||||
#endif
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "i915_drv.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_dp.h"
|
||||
#include "intel_dpll.h"
|
||||
#include "intel_pps.h"
|
||||
|
||||
static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv,
|
||||
|
Loading…
Reference in New Issue
Block a user