mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-19 18:07:10 +07:00
drm/i915/chv: Add update and enable pll for Cherryview
Added programming PLL for CHV based on "Application note for 1273 CHV Display phy". v2: -Break the common lane reset into another patch. -Break the clock calculation into another patch. -The changes are based on Ville review. -Rework based on DPIO register define naming convention change. -Break the dpio write into few lines to improve readability. -Correct the udelay during chv_enable_pll. -clean up some magic numbers with some new define. -program the afc recal bit which was missed. v3: Based on Ville review - minor correction of the bit defination - add deassert/propagate data lane reset v4: Corrected the udelay between dclkp enable and pll enable. Minor comment and better way to clear the TX lane reset. v5: Squash in fixup from Rafael Barbalho. [vsyrjala: v6: Polish the defines (Imre)] Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Imre Deak <imre.deak@intel.com> Signed-off-by: Chon Ming Lee <chon.ming.lee@intel.com> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
parent
ef9348c860
commit
9d556c99ed
@ -681,6 +681,12 @@ enum punit_power_well {
|
||||
#define _VLV_PCS_DW9_CH1 0x8424
|
||||
#define VLV_PCS_DW9(ch) _PORT(ch, _VLV_PCS_DW9_CH0, _VLV_PCS_DW9_CH1)
|
||||
|
||||
#define _CHV_PCS_DW10_CH0 0x8228
|
||||
#define _CHV_PCS_DW10_CH1 0x8428
|
||||
#define DPIO_PCS_SWING_CALC_TX0_TX2 (1<<30)
|
||||
#define DPIO_PCS_SWING_CALC_TX1_TX3 (1<<31)
|
||||
#define CHV_PCS_DW10(ch) _PORT(ch, _CHV_PCS_DW10_CH0, _CHV_PCS_DW10_CH1)
|
||||
|
||||
#define _VLV_PCS_DW11_CH0 0x822c
|
||||
#define _VLV_PCS_DW11_CH1 0x842c
|
||||
#define VLV_PCS_DW11(ch) _PORT(ch, _VLV_PCS_DW11_CH0, _VLV_PCS_DW11_CH1)
|
||||
@ -699,14 +705,21 @@ enum punit_power_well {
|
||||
|
||||
#define _VLV_TX_DW2_CH0 0x8288
|
||||
#define _VLV_TX_DW2_CH1 0x8488
|
||||
#define DPIO_SWING_MARGIN_SHIFT 16
|
||||
#define DPIO_SWING_MARGIN_MASK (0xff << DPIO_SWING_MARGIN_SHIFT)
|
||||
#define DPIO_UNIQ_TRANS_SCALE_SHIFT 8
|
||||
#define VLV_TX_DW2(ch) _PORT(ch, _VLV_TX_DW2_CH0, _VLV_TX_DW2_CH1)
|
||||
|
||||
#define _VLV_TX_DW3_CH0 0x828c
|
||||
#define _VLV_TX_DW3_CH1 0x848c
|
||||
/* The following bit for CHV phy */
|
||||
#define DPIO_TX_UNIQ_TRANS_SCALE_EN (1<<27)
|
||||
#define VLV_TX_DW3(ch) _PORT(ch, _VLV_TX_DW3_CH0, _VLV_TX_DW3_CH1)
|
||||
|
||||
#define _VLV_TX_DW4_CH0 0x8290
|
||||
#define _VLV_TX_DW4_CH1 0x8490
|
||||
#define DPIO_SWING_DEEMPH9P5_SHIFT 24
|
||||
#define DPIO_SWING_DEEMPH9P5_MASK (0xff << DPIO_SWING_DEEMPH9P5_SHIFT)
|
||||
#define VLV_TX_DW4(ch) _PORT(ch, _VLV_TX_DW4_CH0, _VLV_TX_DW4_CH1)
|
||||
|
||||
#define _VLV_TX3_DW4_CH0 0x690
|
||||
@ -726,6 +739,62 @@ enum punit_power_well {
|
||||
#define _VLV_TX_DW14_CH1 0x84b8
|
||||
#define VLV_TX_DW14(ch) _PORT(ch, _VLV_TX_DW14_CH0, _VLV_TX_DW14_CH1)
|
||||
|
||||
/* CHV dpPhy registers */
|
||||
#define _CHV_PLL_DW0_CH0 0x8000
|
||||
#define _CHV_PLL_DW0_CH1 0x8180
|
||||
#define CHV_PLL_DW0(ch) _PIPE(ch, _CHV_PLL_DW0_CH0, _CHV_PLL_DW0_CH1)
|
||||
|
||||
#define _CHV_PLL_DW1_CH0 0x8004
|
||||
#define _CHV_PLL_DW1_CH1 0x8184
|
||||
#define DPIO_CHV_N_DIV_SHIFT 8
|
||||
#define DPIO_CHV_M1_DIV_BY_2 (0 << 0)
|
||||
#define CHV_PLL_DW1(ch) _PIPE(ch, _CHV_PLL_DW1_CH0, _CHV_PLL_DW1_CH1)
|
||||
|
||||
#define _CHV_PLL_DW2_CH0 0x8008
|
||||
#define _CHV_PLL_DW2_CH1 0x8188
|
||||
#define CHV_PLL_DW2(ch) _PIPE(ch, _CHV_PLL_DW2_CH0, _CHV_PLL_DW2_CH1)
|
||||
|
||||
#define _CHV_PLL_DW3_CH0 0x800c
|
||||
#define _CHV_PLL_DW3_CH1 0x818c
|
||||
#define DPIO_CHV_FRAC_DIV_EN (1 << 16)
|
||||
#define DPIO_CHV_FIRST_MOD (0 << 8)
|
||||
#define DPIO_CHV_SECOND_MOD (1 << 8)
|
||||
#define DPIO_CHV_FEEDFWD_GAIN_SHIFT 0
|
||||
#define CHV_PLL_DW3(ch) _PIPE(ch, _CHV_PLL_DW3_CH0, _CHV_PLL_DW3_CH1)
|
||||
|
||||
#define _CHV_PLL_DW6_CH0 0x8018
|
||||
#define _CHV_PLL_DW6_CH1 0x8198
|
||||
#define DPIO_CHV_GAIN_CTRL_SHIFT 16
|
||||
#define DPIO_CHV_INT_COEFF_SHIFT 8
|
||||
#define DPIO_CHV_PROP_COEFF_SHIFT 0
|
||||
#define CHV_PLL_DW6(ch) _PIPE(ch, _CHV_PLL_DW6_CH0, _CHV_PLL_DW6_CH1)
|
||||
|
||||
#define _CHV_CMN_DW13_CH0 0x8134
|
||||
#define _CHV_CMN_DW0_CH1 0x8080
|
||||
#define DPIO_CHV_S1_DIV_SHIFT 21
|
||||
#define DPIO_CHV_P1_DIV_SHIFT 13 /* 3 bits */
|
||||
#define DPIO_CHV_P2_DIV_SHIFT 8 /* 5 bits */
|
||||
#define DPIO_CHV_K_DIV_SHIFT 4
|
||||
#define DPIO_PLL_FREQLOCK (1 << 1)
|
||||
#define DPIO_PLL_LOCK (1 << 0)
|
||||
#define CHV_CMN_DW13(ch) _PIPE(ch, _CHV_CMN_DW13_CH0, _CHV_CMN_DW0_CH1)
|
||||
|
||||
#define _CHV_CMN_DW14_CH0 0x8138
|
||||
#define _CHV_CMN_DW1_CH1 0x8084
|
||||
#define DPIO_AFC_RECAL (1 << 14)
|
||||
#define DPIO_DCLKP_EN (1 << 13)
|
||||
#define CHV_CMN_DW14(ch) _PIPE(ch, _CHV_CMN_DW14_CH0, _CHV_CMN_DW1_CH1)
|
||||
|
||||
#define CHV_CMN_DW30 0x8178
|
||||
#define DPIO_LRC_BYPASS (1 << 3)
|
||||
|
||||
#define _TXLANE(ch, lane, offset) ((ch ? 0x2400 : 0) + \
|
||||
(lane) * 0x200 + (offset))
|
||||
|
||||
#define CHV_TX_DW11(ch, lane) _TXLANE(ch, lane, 0xac)
|
||||
#define DPIO_FRC_LATENCY_SHFIT 8
|
||||
#define CHV_TX_DW14(ch, lane) _TXLANE(ch, lane, 0xb8)
|
||||
#define DPIO_UPAR_SHIFT 30
|
||||
/*
|
||||
* Fence registers
|
||||
*/
|
||||
@ -1415,6 +1484,7 @@ enum punit_power_well {
|
||||
#define DPLL_LOCK_VLV (1<<15)
|
||||
#define DPLL_INTEGRATED_CRI_CLK_VLV (1<<14)
|
||||
#define DPLL_INTEGRATED_CLOCK_VLV (1<<13)
|
||||
#define DPLL_SSC_REF_CLOCK_CHV (1<<13)
|
||||
#define DPLL_PORTC_READY_MASK (0xf << 4)
|
||||
#define DPLL_PORTB_READY_MASK (0xf)
|
||||
|
||||
|
@ -1555,6 +1555,49 @@ static void vlv_enable_pll(struct intel_crtc *crtc)
|
||||
udelay(150); /* wait for warmup */
|
||||
}
|
||||
|
||||
static void chv_enable_pll(struct intel_crtc *crtc)
|
||||
{
|
||||
struct drm_device *dev = crtc->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int pipe = crtc->pipe;
|
||||
enum dpio_channel port = vlv_pipe_to_channel(pipe);
|
||||
int dpll = DPLL(crtc->pipe);
|
||||
u32 tmp;
|
||||
|
||||
assert_pipe_disabled(dev_priv, crtc->pipe);
|
||||
|
||||
BUG_ON(!IS_CHERRYVIEW(dev_priv->dev));
|
||||
|
||||
mutex_lock(&dev_priv->dpio_lock);
|
||||
|
||||
/* 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);
|
||||
|
||||
/*
|
||||
* Need to wait > 100ns between dclkp clock enable bit and PLL enable.
|
||||
*/
|
||||
udelay(1);
|
||||
|
||||
/* Enable PLL */
|
||||
tmp = I915_READ(dpll);
|
||||
tmp |= DPLL_VCO_ENABLE;
|
||||
I915_WRITE(dpll, tmp);
|
||||
|
||||
/* Check PLL is locked */
|
||||
if (wait_for(((I915_READ(dpll) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1))
|
||||
DRM_ERROR("PLL %d failed to lock\n", pipe);
|
||||
|
||||
/* Deassert soft data lane reset*/
|
||||
tmp = vlv_dpio_read(dev_priv, pipe, VLV_PCS_DW0(port));
|
||||
tmp |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port), tmp);
|
||||
|
||||
|
||||
mutex_unlock(&dev_priv->dpio_lock);
|
||||
}
|
||||
|
||||
static void i9xx_enable_pll(struct intel_crtc *crtc)
|
||||
{
|
||||
struct drm_device *dev = crtc->base.dev;
|
||||
@ -4470,8 +4513,12 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
|
||||
|
||||
is_dsi = intel_pipe_has_type(crtc, INTEL_OUTPUT_DSI);
|
||||
|
||||
if (!is_dsi)
|
||||
vlv_enable_pll(intel_crtc);
|
||||
if (!is_dsi) {
|
||||
if (IS_CHERRYVIEW(dev))
|
||||
chv_enable_pll(intel_crtc);
|
||||
else
|
||||
vlv_enable_pll(intel_crtc);
|
||||
}
|
||||
|
||||
for_each_encoder_on_crtc(dev, crtc, encoder)
|
||||
if (encoder->pre_enable)
|
||||
@ -5326,6 +5373,87 @@ static void vlv_update_pll(struct intel_crtc *crtc)
|
||||
mutex_unlock(&dev_priv->dpio_lock);
|
||||
}
|
||||
|
||||
static void chv_update_pll(struct intel_crtc *crtc)
|
||||
{
|
||||
struct drm_device *dev = crtc->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int pipe = crtc->pipe;
|
||||
int dpll_reg = DPLL(crtc->pipe);
|
||||
enum dpio_channel port = vlv_pipe_to_channel(pipe);
|
||||
u32 val, loopfilter, intcoeff;
|
||||
u32 bestn, bestm1, bestm2, bestp1, bestp2, bestm2_frac;
|
||||
int refclk;
|
||||
|
||||
mutex_lock(&dev_priv->dpio_lock);
|
||||
|
||||
bestn = crtc->config.dpll.n;
|
||||
bestm2_frac = crtc->config.dpll.m2 & 0x3fffff;
|
||||
bestm1 = crtc->config.dpll.m1;
|
||||
bestm2 = crtc->config.dpll.m2 >> 22;
|
||||
bestp1 = crtc->config.dpll.p1;
|
||||
bestp2 = crtc->config.dpll.p2;
|
||||
|
||||
/*
|
||||
* Enable Refclk and SSC
|
||||
*/
|
||||
val = I915_READ(dpll_reg);
|
||||
val |= (DPLL_SSC_REF_CLOCK_CHV | DPLL_REFA_CLK_ENABLE_VLV);
|
||||
I915_WRITE(dpll_reg, val);
|
||||
|
||||
/* Propagate soft reset to data lane reset */
|
||||
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS_DW0(port));
|
||||
val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port), val);
|
||||
|
||||
/* 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);
|
||||
|
||||
/* 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 */
|
||||
vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW3(port),
|
||||
DPIO_CHV_FRAC_DIV_EN |
|
||||
(2 << DPIO_CHV_FEEDFWD_GAIN_SHIFT));
|
||||
|
||||
/* Loop filter */
|
||||
refclk = i9xx_get_refclk(&crtc->base, 0);
|
||||
loopfilter = 5 << DPIO_CHV_PROP_COEFF_SHIFT |
|
||||
2 << DPIO_CHV_GAIN_CTRL_SHIFT;
|
||||
if (refclk == 100000)
|
||||
intcoeff = 11;
|
||||
else if (refclk == 38400)
|
||||
intcoeff = 10;
|
||||
else
|
||||
intcoeff = 9;
|
||||
loopfilter |= intcoeff << DPIO_CHV_INT_COEFF_SHIFT;
|
||||
vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW6(port), loopfilter);
|
||||
|
||||
/* 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);
|
||||
|
||||
mutex_unlock(&dev_priv->dpio_lock);
|
||||
}
|
||||
|
||||
static void i9xx_update_pll(struct intel_crtc *crtc,
|
||||
intel_clock_t *reduced_clock,
|
||||
int num_connectors)
|
||||
@ -5709,6 +5837,8 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
|
||||
i8xx_update_pll(intel_crtc,
|
||||
has_reduced_clock ? &reduced_clock : NULL,
|
||||
num_connectors);
|
||||
} else if (IS_CHERRYVIEW(dev)) {
|
||||
chv_update_pll(intel_crtc);
|
||||
} else if (IS_VALLEYVIEW(dev)) {
|
||||
vlv_update_pll(intel_crtc);
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user