mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-21 18:14:48 +08:00
drm/i915/cnl: Get DDI clock based on PLLs.
PLLs are the source clocks for the DDIs so in order to determine the ddi clock we need to check the PLL configuration. v2: Mika pointed out that 24 was hardcoded while it should consider ref clock that can be either 24KHz or 19.2KHz on CNL. Reviewed-by: Mika Kahola <mika.kahola@intel.com> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/1499374321-31152-1-git-send-email-rodrigo.vivi@intel.com
This commit is contained in:
parent
35ceabf3cd
commit
a9701a8970
@ -8343,6 +8343,7 @@ enum {
|
||||
#define DPLL_CFGCR0_LINK_RATE_3240 (6 << 25)
|
||||
#define DPLL_CFGCR0_LINK_RATE_4050 (7 << 25)
|
||||
#define DPLL_CFGCR0_DCO_FRACTION_MASK (0x7fff << 10)
|
||||
#define DPLL_CFGCR0_DCO_FRAC_SHIFT (10)
|
||||
#define DPLL_CFGCR0_DCO_FRACTION(x) ((x) << 10)
|
||||
#define DPLL_CFGCR0_DCO_INTEGER_MASK (0x3ff)
|
||||
#define CNL_DPLL_CFGCR0(pll) _MMIO_PLL(pll, _CNL_DPLL0_CFGCR0, _CNL_DPLL1_CFGCR0)
|
||||
@ -8350,6 +8351,7 @@ enum {
|
||||
#define _CNL_DPLL0_CFGCR1 0x6C004
|
||||
#define _CNL_DPLL1_CFGCR1 0x6C084
|
||||
#define DPLL_CFGCR1_QDIV_RATIO_MASK (0xff << 10)
|
||||
#define DPLL_CFGCR1_QDIV_RATIO_SHIFT (10)
|
||||
#define DPLL_CFGCR1_QDIV_RATIO(x) ((x) << 10)
|
||||
#define DPLL_CFGCR1_QDIV_MODE(x) ((x) << 9)
|
||||
#define DPLL_CFGCR1_KDIV_MASK (7 << 6)
|
||||
|
@ -1103,6 +1103,62 @@ static int skl_calc_wrpll_link(struct drm_i915_private *dev_priv,
|
||||
return dco_freq / (p0 * p1 * p2 * 5);
|
||||
}
|
||||
|
||||
static int cnl_calc_wrpll_link(struct drm_i915_private *dev_priv,
|
||||
uint32_t pll_id)
|
||||
{
|
||||
uint32_t cfgcr0, cfgcr1;
|
||||
uint32_t p0, p1, p2, dco_freq, ref_clock;
|
||||
|
||||
cfgcr0 = I915_READ(CNL_DPLL_CFGCR0(pll_id));
|
||||
cfgcr1 = I915_READ(CNL_DPLL_CFGCR1(pll_id));
|
||||
|
||||
p0 = cfgcr1 & DPLL_CFGCR1_PDIV_MASK;
|
||||
p2 = cfgcr1 & DPLL_CFGCR1_KDIV_MASK;
|
||||
|
||||
if (cfgcr1 & DPLL_CFGCR1_QDIV_MODE(1))
|
||||
p1 = (cfgcr1 & DPLL_CFGCR1_QDIV_RATIO_MASK) >>
|
||||
DPLL_CFGCR1_QDIV_RATIO_SHIFT;
|
||||
else
|
||||
p1 = 1;
|
||||
|
||||
|
||||
switch (p0) {
|
||||
case DPLL_CFGCR1_PDIV_2:
|
||||
p0 = 2;
|
||||
break;
|
||||
case DPLL_CFGCR1_PDIV_3:
|
||||
p0 = 3;
|
||||
break;
|
||||
case DPLL_CFGCR1_PDIV_5:
|
||||
p0 = 5;
|
||||
break;
|
||||
case DPLL_CFGCR1_PDIV_7:
|
||||
p0 = 7;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (p2) {
|
||||
case DPLL_CFGCR1_KDIV_1:
|
||||
p2 = 1;
|
||||
break;
|
||||
case DPLL_CFGCR1_KDIV_2:
|
||||
p2 = 2;
|
||||
break;
|
||||
case DPLL_CFGCR1_KDIV_4:
|
||||
p2 = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
ref_clock = dev_priv->cdclk.hw.ref;
|
||||
|
||||
dco_freq = (cfgcr0 & DPLL_CFGCR0_DCO_INTEGER_MASK) * ref_clock;
|
||||
|
||||
dco_freq += (((cfgcr0 & DPLL_CFGCR0_DCO_FRACTION_MASK) >>
|
||||
DPLL_CFGCR0_DCO_FRAC_SHIFT) * ref_clock) / 0x8000;
|
||||
|
||||
return dco_freq / (p0 * p1 * p2 * 5);
|
||||
}
|
||||
|
||||
static void ddi_dotclock_get(struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
int dotclock;
|
||||
@ -1124,6 +1180,59 @@ static void ddi_dotclock_get(struct intel_crtc_state *pipe_config)
|
||||
pipe_config->base.adjusted_mode.crtc_clock = dotclock;
|
||||
}
|
||||
|
||||
static void cnl_ddi_clock_get(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
int link_clock = 0;
|
||||
uint32_t cfgcr0, pll_id;
|
||||
|
||||
pll_id = intel_get_shared_dpll_id(dev_priv, pipe_config->shared_dpll);
|
||||
|
||||
cfgcr0 = I915_READ(CNL_DPLL_CFGCR0(pll_id));
|
||||
|
||||
if (cfgcr0 & DPLL_CFGCR0_HDMI_MODE) {
|
||||
link_clock = cnl_calc_wrpll_link(dev_priv, pll_id);
|
||||
} else {
|
||||
link_clock = cfgcr0 & DPLL_CFGCR0_LINK_RATE_MASK;
|
||||
|
||||
switch (link_clock) {
|
||||
case DPLL_CFGCR0_LINK_RATE_810:
|
||||
link_clock = 81000;
|
||||
break;
|
||||
case DPLL_CFGCR0_LINK_RATE_1080:
|
||||
link_clock = 108000;
|
||||
break;
|
||||
case DPLL_CFGCR0_LINK_RATE_1350:
|
||||
link_clock = 135000;
|
||||
break;
|
||||
case DPLL_CFGCR0_LINK_RATE_1620:
|
||||
link_clock = 162000;
|
||||
break;
|
||||
case DPLL_CFGCR0_LINK_RATE_2160:
|
||||
link_clock = 216000;
|
||||
break;
|
||||
case DPLL_CFGCR0_LINK_RATE_2700:
|
||||
link_clock = 270000;
|
||||
break;
|
||||
case DPLL_CFGCR0_LINK_RATE_3240:
|
||||
link_clock = 324000;
|
||||
break;
|
||||
case DPLL_CFGCR0_LINK_RATE_4050:
|
||||
link_clock = 405000;
|
||||
break;
|
||||
default:
|
||||
WARN(1, "Unsupported link rate\n");
|
||||
break;
|
||||
}
|
||||
link_clock *= 2;
|
||||
}
|
||||
|
||||
pipe_config->port_clock = link_clock;
|
||||
|
||||
ddi_dotclock_get(pipe_config);
|
||||
}
|
||||
|
||||
static void skl_ddi_clock_get(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
@ -1267,6 +1376,8 @@ void intel_ddi_clock_get(struct intel_encoder *encoder,
|
||||
skl_ddi_clock_get(encoder, pipe_config);
|
||||
else if (IS_GEN9_LP(dev_priv))
|
||||
bxt_ddi_clock_get(encoder, pipe_config);
|
||||
else if (IS_CANNONLAKE(dev_priv))
|
||||
cnl_ddi_clock_get(encoder, pipe_config);
|
||||
}
|
||||
|
||||
void intel_ddi_set_pipe_settings(const struct intel_crtc_state *crtc_state)
|
||||
|
Loading…
Reference in New Issue
Block a user