Commit 49cd97a3 authored by Ville Syrjälä's avatar Ville Syrjälä

drm/i915: Start moving the cdclk stuff into a distinct state structure

Introduce intel_cdclk state which for now will track the cdclk
frequency, the vco frequency and the reference frequency (not sure we
want the last one, but I put it there anyway). We'll also make the
.get_cdclk() function fill out this state structure rather than
just returning the current cdclk frequency.

One immediate benefit is that calling .get_cdclk() will no longer
clobber state stored under dev_priv unless ex[plicitly told to do
so. Previously it clobbered the vco and reference clocks stored
there on some platforms.

We'll expand the use of this structure to actually precomputing the
state and whatnot later.

v2: Constify intel_cdclk_state_compare()
v3: Document intel_cdclk_state_compare()
v4: Deal with i945gm_get_cdclk()
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: default avatarAnder Conselvan de Oliveira <conselvan2@gmail.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170207183345.19763-1-ville.syrjala@linux.intel.com
parent 8f0cfa4d
...@@ -1281,7 +1281,7 @@ static int i915_frequency_info(struct seq_file *m, void *unused) ...@@ -1281,7 +1281,7 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
seq_puts(m, "no P-state info available\n"); seq_puts(m, "no P-state info available\n");
} }
seq_printf(m, "Current CD clock frequency: %d kHz\n", dev_priv->cdclk_freq); seq_printf(m, "Current CD clock frequency: %d kHz\n", dev_priv->cdclk.hw.cdclk);
seq_printf(m, "Max CD clock frequency: %d kHz\n", dev_priv->max_cdclk_freq); seq_printf(m, "Max CD clock frequency: %d kHz\n", dev_priv->max_cdclk_freq);
seq_printf(m, "Max pixel clock frequency: %d kHz\n", dev_priv->max_dotclk_freq); seq_printf(m, "Max pixel clock frequency: %d kHz\n", dev_priv->max_dotclk_freq);
......
...@@ -600,9 +600,11 @@ struct intel_initial_plane_config; ...@@ -600,9 +600,11 @@ struct intel_initial_plane_config;
struct intel_crtc; struct intel_crtc;
struct intel_limit; struct intel_limit;
struct dpll; struct dpll;
struct intel_cdclk_state;
struct drm_i915_display_funcs { struct drm_i915_display_funcs {
int (*get_cdclk)(struct drm_i915_private *dev_priv); void (*get_cdclk)(struct drm_i915_private *dev_priv,
struct intel_cdclk_state *cdclk_state);
int (*get_fifo_size)(struct drm_i915_private *dev_priv, int plane); int (*get_fifo_size)(struct drm_i915_private *dev_priv, int plane);
int (*compute_pipe_wm)(struct intel_crtc_state *cstate); int (*compute_pipe_wm)(struct intel_crtc_state *cstate);
int (*compute_intermediate_wm)(struct drm_device *dev, int (*compute_intermediate_wm)(struct drm_device *dev,
...@@ -2060,6 +2062,10 @@ struct i915_oa_ops { ...@@ -2060,6 +2062,10 @@ struct i915_oa_ops {
bool (*oa_buffer_is_empty)(struct drm_i915_private *dev_priv); bool (*oa_buffer_is_empty)(struct drm_i915_private *dev_priv);
}; };
struct intel_cdclk_state {
unsigned int cdclk, vco, ref;
};
struct drm_i915_private { struct drm_i915_private {
struct drm_device drm; struct drm_device drm;
...@@ -2164,7 +2170,7 @@ struct drm_i915_private { ...@@ -2164,7 +2170,7 @@ struct drm_i915_private {
unsigned int fsb_freq, mem_freq, is_ddr3; unsigned int fsb_freq, mem_freq, is_ddr3;
unsigned int skl_preferred_vco_freq; unsigned int skl_preferred_vco_freq;
unsigned int cdclk_freq, max_cdclk_freq; unsigned int max_cdclk_freq;
/* /*
* For reading holding any crtc lock is sufficient, * For reading holding any crtc lock is sufficient,
...@@ -2178,8 +2184,8 @@ struct drm_i915_private { ...@@ -2178,8 +2184,8 @@ struct drm_i915_private {
unsigned int czclk_freq; unsigned int czclk_freq;
struct { struct {
unsigned int vco, ref; struct intel_cdclk_state hw;
} cdclk_pll; } cdclk;
/** /**
* wq - Driver workqueue for GEM. * wq - Driver workqueue for GEM.
......
...@@ -734,7 +734,7 @@ static int i915_audio_component_get_cdclk_freq(struct device *kdev) ...@@ -734,7 +734,7 @@ static int i915_audio_component_get_cdclk_freq(struct device *kdev)
if (WARN_ON_ONCE(!HAS_DDI(dev_priv))) if (WARN_ON_ONCE(!HAS_DDI(dev_priv)))
return -ENODEV; return -ENODEV;
return dev_priv->cdclk_freq; return dev_priv->cdclk.hw.cdclk;
} }
/* /*
......
...@@ -51,37 +51,44 @@ ...@@ -51,37 +51,44 @@
* dividers can be programmed correctly. * dividers can be programmed correctly.
*/ */
static int fixed_133mhz_get_cdclk(struct drm_i915_private *dev_priv) static void fixed_133mhz_get_cdclk(struct drm_i915_private *dev_priv,
struct intel_cdclk_state *cdclk_state)
{ {
return 133333; cdclk_state->cdclk = 133333;
} }
static int fixed_200mhz_get_cdclk(struct drm_i915_private *dev_priv) static void fixed_200mhz_get_cdclk(struct drm_i915_private *dev_priv,
struct intel_cdclk_state *cdclk_state)
{ {
return 200000; cdclk_state->cdclk = 200000;
} }
static int fixed_266mhz_get_cdclk(struct drm_i915_private *dev_priv) static void fixed_266mhz_get_cdclk(struct drm_i915_private *dev_priv,
struct intel_cdclk_state *cdclk_state)
{ {
return 266667; cdclk_state->cdclk = 266667;
} }
static int fixed_333mhz_get_cdclk(struct drm_i915_private *dev_priv) static void fixed_333mhz_get_cdclk(struct drm_i915_private *dev_priv,
struct intel_cdclk_state *cdclk_state)
{ {
return 333333; cdclk_state->cdclk = 333333;
} }
static int fixed_400mhz_get_cdclk(struct drm_i915_private *dev_priv) static void fixed_400mhz_get_cdclk(struct drm_i915_private *dev_priv,
struct intel_cdclk_state *cdclk_state)
{ {
return 400000; cdclk_state->cdclk = 400000;
} }
static int fixed_450mhz_get_cdclk(struct drm_i915_private *dev_priv) static void fixed_450mhz_get_cdclk(struct drm_i915_private *dev_priv,
struct intel_cdclk_state *cdclk_state)
{ {
return 450000; cdclk_state->cdclk = 450000;
} }
static int i85x_get_cdclk(struct drm_i915_private *dev_priv) static void i85x_get_cdclk(struct drm_i915_private *dev_priv,
struct intel_cdclk_state *cdclk_state)
{ {
struct pci_dev *pdev = dev_priv->drm.pdev; struct pci_dev *pdev = dev_priv->drm.pdev;
u16 hpllcc = 0; u16 hpllcc = 0;
...@@ -91,8 +98,10 @@ static int i85x_get_cdclk(struct drm_i915_private *dev_priv) ...@@ -91,8 +98,10 @@ static int i85x_get_cdclk(struct drm_i915_private *dev_priv)
* encoding is different :( * encoding is different :(
* FIXME is this the right way to detect 852GM/852GMV? * FIXME is this the right way to detect 852GM/852GMV?
*/ */
if (pdev->revision == 0x1) if (pdev->revision == 0x1) {
return 133333; cdclk_state->cdclk = 133333;
return;
}
pci_bus_read_config_word(pdev->bus, pci_bus_read_config_word(pdev->bus,
PCI_DEVFN(0, 3), HPLLCC, &hpllcc); PCI_DEVFN(0, 3), HPLLCC, &hpllcc);
...@@ -104,56 +113,67 @@ static int i85x_get_cdclk(struct drm_i915_private *dev_priv) ...@@ -104,56 +113,67 @@ static int i85x_get_cdclk(struct drm_i915_private *dev_priv)
case GC_CLOCK_133_200: case GC_CLOCK_133_200:
case GC_CLOCK_133_200_2: case GC_CLOCK_133_200_2:
case GC_CLOCK_100_200: case GC_CLOCK_100_200:
return 200000; cdclk_state->cdclk = 200000;
break;
case GC_CLOCK_166_250: case GC_CLOCK_166_250:
return 250000; cdclk_state->cdclk = 250000;
break;
case GC_CLOCK_100_133: case GC_CLOCK_100_133:
return 133333; cdclk_state->cdclk = 133333;
break;
case GC_CLOCK_133_266: case GC_CLOCK_133_266:
case GC_CLOCK_133_266_2: case GC_CLOCK_133_266_2:
case GC_CLOCK_166_266: case GC_CLOCK_166_266:
return 266667; cdclk_state->cdclk = 266667;
break;
} }
/* Shouldn't happen */
return 0;
} }
static int i915gm_get_cdclk(struct drm_i915_private *dev_priv) static void i915gm_get_cdclk(struct drm_i915_private *dev_priv,
struct intel_cdclk_state *cdclk_state)
{ {
struct pci_dev *pdev = dev_priv->drm.pdev; struct pci_dev *pdev = dev_priv->drm.pdev;
u16 gcfgc = 0; u16 gcfgc = 0;
pci_read_config_word(pdev, GCFGC, &gcfgc); pci_read_config_word(pdev, GCFGC, &gcfgc);
if (gcfgc & GC_LOW_FREQUENCY_ENABLE) if (gcfgc & GC_LOW_FREQUENCY_ENABLE) {
return 133333; cdclk_state->cdclk = 133333;
return;
}
switch (gcfgc & GC_DISPLAY_CLOCK_MASK) { switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
case GC_DISPLAY_CLOCK_333_320_MHZ: case GC_DISPLAY_CLOCK_333_320_MHZ:
return 333333; cdclk_state->cdclk = 333333;
break;
default: default:
case GC_DISPLAY_CLOCK_190_200_MHZ: case GC_DISPLAY_CLOCK_190_200_MHZ:
return 190000; cdclk_state->cdclk = 190000;
break;
} }
} }
static int i945gm_get_cdclk(struct drm_i915_private *dev_priv) static void i945gm_get_cdclk(struct drm_i915_private *dev_priv,
struct intel_cdclk_state *cdclk_state)
{ {
struct pci_dev *pdev = dev_priv->drm.pdev; struct pci_dev *pdev = dev_priv->drm.pdev;
u16 gcfgc = 0; u16 gcfgc = 0;
pci_read_config_word(pdev, GCFGC, &gcfgc); pci_read_config_word(pdev, GCFGC, &gcfgc);
if (gcfgc & GC_LOW_FREQUENCY_ENABLE) if (gcfgc & GC_LOW_FREQUENCY_ENABLE) {
return 133333; cdclk_state->cdclk = 133333;
return;
}
switch (gcfgc & GC_DISPLAY_CLOCK_MASK) { switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
case GC_DISPLAY_CLOCK_333_320_MHZ: case GC_DISPLAY_CLOCK_333_320_MHZ:
return 320000; cdclk_state->cdclk = 320000;
break;
default: default:
case GC_DISPLAY_CLOCK_190_200_MHZ: case GC_DISPLAY_CLOCK_190_200_MHZ:
return 200000; cdclk_state->cdclk = 200000;
break;
} }
} }
...@@ -225,7 +245,8 @@ static unsigned int intel_hpll_vco(struct drm_i915_private *dev_priv) ...@@ -225,7 +245,8 @@ static unsigned int intel_hpll_vco(struct drm_i915_private *dev_priv)
return vco; return vco;
} }
static int g33_get_cdclk(struct drm_i915_private *dev_priv) static void g33_get_cdclk(struct drm_i915_private *dev_priv,
struct intel_cdclk_state *cdclk_state)
{ {
struct pci_dev *pdev = dev_priv->drm.pdev; struct pci_dev *pdev = dev_priv->drm.pdev;
static const uint8_t div_3200[] = { 12, 10, 8, 7, 5, 16 }; static const uint8_t div_3200[] = { 12, 10, 8, 7, 5, 16 };
...@@ -233,9 +254,11 @@ static int g33_get_cdclk(struct drm_i915_private *dev_priv) ...@@ -233,9 +254,11 @@ static int g33_get_cdclk(struct drm_i915_private *dev_priv)
static const uint8_t div_4800[] = { 20, 14, 12, 10, 8, 24 }; static const uint8_t div_4800[] = { 20, 14, 12, 10, 8, 24 };
static const uint8_t div_5333[] = { 20, 16, 12, 12, 8, 28 }; static const uint8_t div_5333[] = { 20, 16, 12, 12, 8, 28 };
const uint8_t *div_table; const uint8_t *div_table;
unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv); unsigned int cdclk_sel;
uint16_t tmp = 0; uint16_t tmp = 0;
cdclk_state->vco = intel_hpll_vco(dev_priv);
pci_read_config_word(pdev, GCFGC, &tmp); pci_read_config_word(pdev, GCFGC, &tmp);
cdclk_sel = (tmp >> 4) & 0x7; cdclk_sel = (tmp >> 4) & 0x7;
...@@ -243,7 +266,7 @@ static int g33_get_cdclk(struct drm_i915_private *dev_priv) ...@@ -243,7 +266,7 @@ static int g33_get_cdclk(struct drm_i915_private *dev_priv)
if (cdclk_sel >= ARRAY_SIZE(div_3200)) if (cdclk_sel >= ARRAY_SIZE(div_3200))
goto fail; goto fail;
switch (vco) { switch (cdclk_state->vco) {
case 3200000: case 3200000:
div_table = div_3200; div_table = div_3200;
break; break;
...@@ -260,15 +283,18 @@ static int g33_get_cdclk(struct drm_i915_private *dev_priv) ...@@ -260,15 +283,18 @@ static int g33_get_cdclk(struct drm_i915_private *dev_priv)
goto fail; goto fail;
} }
return DIV_ROUND_CLOSEST(vco, div_table[cdclk_sel]); cdclk_state->cdclk = DIV_ROUND_CLOSEST(cdclk_state->vco,
div_table[cdclk_sel]);
return;
fail: fail:
DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz, CFGC=0x%08x\n", DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz, CFGC=0x%08x\n",
vco, tmp); cdclk_state->vco, tmp);
return 190476; cdclk_state->cdclk = 190476;
} }
static int pnv_get_cdclk(struct drm_i915_private *dev_priv) static void pnv_get_cdclk(struct drm_i915_private *dev_priv,
struct intel_cdclk_state *cdclk_state)
{ {
struct pci_dev *pdev = dev_priv->drm.pdev; struct pci_dev *pdev = dev_priv->drm.pdev;
u16 gcfgc = 0; u16 gcfgc = 0;
...@@ -277,32 +303,41 @@ static int pnv_get_cdclk(struct drm_i915_private *dev_priv) ...@@ -277,32 +303,41 @@ static int pnv_get_cdclk(struct drm_i915_private *dev_priv)
switch (gcfgc & GC_DISPLAY_CLOCK_MASK) { switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
case GC_DISPLAY_CLOCK_267_MHZ_PNV: case GC_DISPLAY_CLOCK_267_MHZ_PNV:
return 266667; cdclk_state->cdclk = 266667;
break;
case GC_DISPLAY_CLOCK_333_MHZ_PNV: case GC_DISPLAY_CLOCK_333_MHZ_PNV:
return 333333; cdclk_state->cdclk = 333333;
break;
case GC_DISPLAY_CLOCK_444_MHZ_PNV: case GC_DISPLAY_CLOCK_444_MHZ_PNV:
return 444444; cdclk_state->cdclk = 444444;
break;
case GC_DISPLAY_CLOCK_200_MHZ_PNV: case GC_DISPLAY_CLOCK_200_MHZ_PNV:
return 200000; cdclk_state->cdclk = 200000;
break;
default: default:
DRM_ERROR("Unknown pnv display core clock 0x%04x\n", gcfgc); DRM_ERROR("Unknown pnv display core clock 0x%04x\n", gcfgc);
case GC_DISPLAY_CLOCK_133_MHZ_PNV: case GC_DISPLAY_CLOCK_133_MHZ_PNV:
return 133333; cdclk_state->cdclk = 133333;
break;
case GC_DISPLAY_CLOCK_167_MHZ_PNV: case GC_DISPLAY_CLOCK_167_MHZ_PNV:
return 166667; cdclk_state->cdclk = 166667;
break;
} }
} }
static int i965gm_get_cdclk(struct drm_i915_private *dev_priv) static void i965gm_get_cdclk(struct drm_i915_private *dev_priv,
struct intel_cdclk_state *cdclk_state)
{ {
struct pci_dev *pdev = dev_priv->drm.pdev; struct pci_dev *pdev = dev_priv->drm.pdev;
static const uint8_t div_3200[] = { 16, 10, 8 }; static const uint8_t div_3200[] = { 16, 10, 8 };
static const uint8_t div_4000[] = { 20, 12, 10 }; static const uint8_t div_4000[] = { 20, 12, 10 };
static const uint8_t div_5333[] = { 24, 16, 14 }; static const uint8_t div_5333[] = { 24, 16, 14 };
const uint8_t *div_table; const uint8_t *div_table;
unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv); unsigned int cdclk_sel;
uint16_t tmp = 0; uint16_t tmp = 0;
cdclk_state->vco = intel_hpll_vco(dev_priv);
pci_read_config_word(pdev, GCFGC, &tmp); pci_read_config_word(pdev, GCFGC, &tmp);
cdclk_sel = ((tmp >> 8) & 0x1f) - 1; cdclk_sel = ((tmp >> 8) & 0x1f) - 1;
...@@ -310,7 +345,7 @@ static int i965gm_get_cdclk(struct drm_i915_private *dev_priv) ...@@ -310,7 +345,7 @@ static int i965gm_get_cdclk(struct drm_i915_private *dev_priv)
if (cdclk_sel >= ARRAY_SIZE(div_3200)) if (cdclk_sel >= ARRAY_SIZE(div_3200))
goto fail; goto fail;
switch (vco) { switch (cdclk_state->vco) {
case 3200000: case 3200000:
div_table = div_3200; div_table = div_3200;
break; break;
...@@ -324,53 +359,62 @@ static int i965gm_get_cdclk(struct drm_i915_private *dev_priv) ...@@ -324,53 +359,62 @@ static int i965gm_get_cdclk(struct drm_i915_private *dev_priv)
goto fail; goto fail;
} }
return DIV_ROUND_CLOSEST(vco, div_table[cdclk_sel]); cdclk_state->cdclk = DIV_ROUND_CLOSEST(cdclk_state->vco,
div_table[cdclk_sel]);
return;
fail: fail:
DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz, CFGC=0x%04x\n", DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz, CFGC=0x%04x\n",
vco, tmp); cdclk_state->vco, tmp);
return 200000; cdclk_state->cdclk = 200000;
} }
static int gm45_get_cdclk(struct drm_i915_private *dev_priv) static void gm45_get_cdclk(struct drm_i915_private *dev_priv,
struct intel_cdclk_state *cdclk_state)
{ {
struct pci_dev *pdev = dev_priv->drm.pdev; struct pci_dev *pdev = dev_priv->drm.pdev;
unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv); unsigned int cdclk_sel;
uint16_t tmp = 0; uint16_t tmp = 0;
cdclk_state->vco = intel_hpll_vco(dev_priv);
pci_read_config_word(pdev, GCFGC, &tmp); pci_read_config_word(pdev, GCFGC, &tmp);
cdclk_sel = (tmp >> 12) & 0x1; cdclk_sel = (tmp >> 12) & 0x1;
switch (vco) { switch (cdclk_state->vco) {
case 2666667: case 2666667:
case 4000000: case 4000000:
case 5333333: case 5333333:
return cdclk_sel ? 333333 : 222222; cdclk_state->cdclk = cdclk_sel ? 333333 : 222222;
break;
case 3200000: case 3200000:
return cdclk_sel ? 320000 : 228571; cdclk_state->cdclk = cdclk_sel ? 320000 : 228571;
break;
default: default:
DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u, CFGC=0x%04x\n", DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u, CFGC=0x%04x\n",
vco, tmp); cdclk_state->vco, tmp);
return 222222; cdclk_state->cdclk = 222222;
break;
} }
} }
static int hsw_get_cdclk(struct drm_i915_private *dev_priv) static void hsw_get_cdclk(struct drm_i915_private *dev_priv,
struct intel_cdclk_state *cdclk_state)
{ {
uint32_t lcpll = I915_READ(LCPLL_CTL); uint32_t lcpll = I915_READ(LCPLL_CTL);
uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK; uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
if (lcpll & LCPLL_CD_SOURCE_FCLK) if (lcpll & LCPLL_CD_SOURCE_FCLK)
return 800000; cdclk_state->cdclk = 800000;
else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT) else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
return 450000; cdclk_state->cdclk = 450000;
else if (freq == LCPLL_CLK_FREQ_450) else if (freq == LCPLL_CLK_FREQ_450)
return 450000; cdclk_state->cdclk = 450000;
else if (IS_HSW_ULT(dev_priv)) else if (IS_HSW_ULT(dev_priv))
return 337500; cdclk_state->cdclk = 337500;
else else
return 540000; cdclk_state->cdclk = 540000;
} }
static int vlv_calc_cdclk(struct drm_i915_private *dev_priv, static int vlv_calc_cdclk(struct drm_i915_private *dev_priv,
...@@ -396,10 +440,13 @@ static int vlv_calc_cdclk(struct drm_i915_private *dev_priv, ...@@ -396,10 +440,13 @@ static int vlv_calc_cdclk(struct drm_i915_private *dev_priv,
return 200000; return 200000;
} }
static int vlv_get_cdclk(struct drm_i915_private *dev_priv) static void vlv_get_cdclk(struct drm_i915_private *dev_priv,
struct intel_cdclk_state *cdclk_state)
{ {
return vlv_get_cck_clock_hpll(dev_priv, "cdclk", cdclk_state->vco = vlv_get_hpll_vco(dev_priv);
CCK_DISPLAY_CLOCK_CONTROL); cdclk_state->cdclk = vlv_get_cck_clock(dev_priv, "cdclk",
CCK_DISPLAY_CLOCK_CONTROL,
cdclk_state->vco);
} }
static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv) static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv)
...@@ -411,7 +458,7 @@ static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv) ...@@ -411,7 +458,7 @@ static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv)
else else
default_credits = PFI_CREDIT(8); default_credits = PFI_CREDIT(8);
if (dev_priv->cdclk_freq >= dev_priv->czclk_freq) { if (dev_priv->cdclk.hw.cdclk >= dev_priv->czclk_freq) {
/* CHV suggested value is 31 or 63 */ /* CHV suggested value is 31 or 63 */
if (IS_CHERRYVIEW(dev_priv)) if (IS_CHERRYVIEW(dev_priv))
credits = PFI_CREDIT_63; credits = PFI_CREDIT_63;
...@@ -443,8 +490,6 @@ static void vlv_set_cdclk(struct drm_device *dev, int cdclk) ...@@ -443,8 +490,6 @@ static void vlv_set_cdclk(struct drm_device *dev, int cdclk)
struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_private *dev_priv = to_i915(dev);
u32 val, cmd; u32 val, cmd;
WARN_ON(dev_priv->display.get_cdclk(dev_priv) != dev_priv->cdclk_freq);
if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */ if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */
cmd = 2; cmd = 2;
else if (cdclk == 266667) else if (cdclk == 266667)
...@@ -508,8 +553,6 @@ static void chv_set_cdclk(struct drm_device *dev, int cdclk) ...@@ -508,8 +553,6 @@ static void chv_set_cdclk(struct drm_device *dev, int cdclk)
struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_private *dev_priv = to_i915(dev);
u32 val, cmd; u32 val, cmd;
WARN_ON(dev_priv->display.get_cdclk(dev_priv) != dev_priv->cdclk_freq);
switch (cdclk) { switch (cdclk) {
case 333333: case 333333:
case 320000: case 320000:
...@@ -555,23 +598,24 @@ static int bdw_calc_cdclk(int max_pixclk) ...@@ -555,23 +598,24 @@ static int bdw_calc_cdclk(int max_pixclk)
return 337500; return 337500;
} }
static int bdw_get_cdclk(struct drm_i915_private *dev_priv) static void bdw_get_cdclk(struct drm_i915_private *dev_priv,
struct intel_cdclk_state *cdclk_state)
{ {
uint32_t lcpll = I915_READ(LCPLL_CTL); uint32_t lcpll = I915_READ(LCPLL_CTL);
uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK; uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
if (lcpll & LCPLL_CD_SOURCE_FCLK) if (lcpll & LCPLL_CD_SOURCE_FCLK)
return 800000; cdclk_state->cdclk = 800000;
else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT) else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
return 450000; cdclk_state->cdclk = 450000;
else if (freq == LCPLL_CLK_FREQ_450) else if (freq == LCPLL_CLK_FREQ_450)
return 450000; cdclk_state->cdclk = 450000;
else if (freq == LCPLL_CLK_FREQ_54O_BDW) else if (freq == LCPLL_CLK_FREQ_54O_BDW)
return 540000; cdclk_state->cdclk = 540000;
else if (freq == LCPLL_CLK_FREQ_337_5_BDW) else if (freq == LCPLL_CLK_FREQ_337_5_BDW)
return 337500; cdclk_state->cdclk = 337500;
else else
return 675000; cdclk_state->cdclk = 675000;
} }
static void bdw_set_cdclk(struct drm_device *dev, int cdclk) static void bdw_set_cdclk(struct drm_device *dev, int cdclk)
...@@ -648,9 +692,9 @@ static void bdw_set_cdclk(struct drm_device *dev, int cdclk) ...@@ -648,9 +692,9 @@ static void bdw_set_cdclk(struct drm_device *dev, int cdclk)
intel_update_cdclk(dev_priv); intel_update_cdclk(dev_priv);
WARN(cdclk != dev_priv->cdclk_freq, WARN(cdclk != dev_priv->cdclk.hw.cdclk,
"cdclk requested %d kHz but got %d kHz\n", "cdclk requested %d kHz but got %d kHz\n",
cdclk, dev_priv->cdclk_freq); cdclk, dev_priv->cdclk.hw.cdclk);
} }
static int skl_calc_cdclk(int max_pixclk, int vco) static int skl_calc_cdclk(int max_pixclk, int vco)
...@@ -676,12 +720,13 @@ static int skl_calc_cdclk(int max_pixclk, int vco) ...@@ -676,12 +720,13 @@ static int skl_calc_cdclk(int max_pixclk, int vco)
} }
} }
static void skl_dpll0_update(struct drm_i915_private *dev_priv) static void skl_dpll0_update(struct drm_i915_private *dev_priv,
struct intel_cdclk_state *cdclk_state)
{ {
u32 val; u32 val;
dev_priv->cdclk_pll.ref = 24000; cdclk_state->ref = 24000;
dev_priv->cdclk_pll.vco = 0; cdclk_state->vco = 0;
val = I915_READ(LCPLL1_CTL); val = I915_READ(LCPLL1_CTL);
if ((val & LCPLL_PLL_ENABLE) == 0) if ((val & LCPLL_PLL_ENABLE) == 0)
...@@ -703,11 +748,11 @@ static void skl_dpll0_update(struct drm_i915_private *dev_priv) ...@@ -703,11 +748,11 @@ static void skl_dpll0_update(struct drm_i915_private *dev_priv)
case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, SKL_DPLL0): case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, SKL_DPLL0):
case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, SKL_DPLL0): case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, SKL_DPLL0):
case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, SKL_DPLL0): case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, SKL_DPLL0):
dev_priv->cdclk_pll.vco = 8100000; cdclk_state->vco = 8100000;
break; break;
case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, SKL_DPLL0): case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, SKL_DPLL0):
case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, SKL_DPLL0): case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, SKL_DPLL0):
dev_priv->cdclk_pll.vco = 8640000; cdclk_state->vco = 8640000;
break; break;
default: default:
MISSING_CASE(val & DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0)); MISSING_CASE(val & DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0));
...@@ -715,46 +760,57 @@ static void skl_dpll0_update(struct drm_i915_private *dev_priv) ...@@ -715,46 +760,57 @@ static void skl_dpll0_update(struct drm_i915_private *dev_priv)
} }
} }
static int skl_get_cdclk(struct drm_i915_private *dev_priv) static void skl_get_cdclk(struct drm_i915_private *dev_priv,
struct intel_cdclk_state *cdclk_state)
{ {
u32 cdctl; u32 cdctl;
skl_dpll0_update(dev_priv); skl_dpll0_update(dev_priv, cdclk_state);
if (dev_priv->cdclk_pll.vco == 0) cdclk_state->cdclk = cdclk_state->ref;
return dev_priv->cdclk_pll.ref;
if (cdclk_state->vco == 0)
return;
cdctl = I915_READ(CDCLK_CTL); cdctl = I915_READ(CDCLK_CTL);
if (dev_priv->cdclk_pll.vco == 8640000) { if (cdclk_state->vco == 8640000) {
switch (cdctl & CDCLK_FREQ_SEL_MASK) { switch (cdctl & CDCLK_FREQ_SEL_MASK) {
case CDCLK_FREQ_450_432: case CDCLK_FREQ_450_432:
return 432000; cdclk_state->cdclk = 432000;
break;
case CDCLK_FREQ_337_308: case CDCLK_FREQ_337_308:
return 308571; cdclk_state->cdclk = 308571;
break;
case CDCLK_FREQ_540: case CDCLK_FREQ_540:
return 540000; cdclk_state->cdclk = 540000;
break;
case CDCLK_FREQ_675_617: case CDCLK_FREQ_675_617:
return 617143; cdclk_state->cdclk = 617143;
break;
default: default:
MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK); MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
break;
} }
} else { } else {
switch (cdctl & CDCLK_FREQ_SEL_MASK) { switch (cdctl & CDCLK_FREQ_SEL_MASK) {
case CDCLK_FREQ_450_432: case CDCLK_FREQ_450_432:
return 450000; cdclk_state->cdclk = 450000;
break;
case CDCLK_FREQ_337_308: case CDCLK_FREQ_337_308:
return 337500; cdclk_state->cdclk = 337500;
break;
case CDCLK_FREQ_540: case CDCLK_FREQ_540:
return 540000; cdclk_state->cdclk = 540000;
break;
case CDCLK_FREQ_675_617: case CDCLK_FREQ_675_617:
return 675000; cdclk_state->cdclk = 675000;
break;
default: default:
MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK); MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
break;
} }
} }
return dev_priv->cdclk_pll.ref;
} }
/* convert from kHz to .1 fixpoint MHz with -1MHz offset */ /* convert from kHz to .1 fixpoint MHz with -1MHz offset */
...@@ -817,7 +873,7 @@ static void skl_dpll0_enable(struct drm_i915_private *dev_priv, int vco) ...@@ -817,7 +873,7 @@ static void skl_dpll0_enable(struct drm_i915_private *dev_priv, int vco)
5)) 5))
DRM_ERROR("DPLL0 not locked\n"); DRM_ERROR("DPLL0 not locked\n");
dev_priv->cdclk_pll.vco = vco; dev_priv->cdclk.hw.vco = vco;
/* We'll want to keep using the current vco from now on. */ /* We'll want to keep using the current vco from now on. */
skl_set_preferred_cdclk_vco(dev_priv, vco); skl_set_preferred_cdclk_vco(dev_priv, vco);
...@@ -831,7 +887,7 @@ static void skl_dpll0_disable(struct drm_i915_private *dev_priv) ...@@ -831,7 +887,7 @@ static void skl_dpll0_disable(struct drm_i915_private *dev_priv)
1)) 1))
DRM_ERROR("Couldn't disable DPLL0\n"); DRM_ERROR("Couldn't disable DPLL0\n");
dev_priv->cdclk_pll.vco = 0; dev_priv->cdclk.hw.vco = 0;
} }
static void skl_set_cdclk(struct drm_i915_private *dev_priv, static void skl_set_cdclk(struct drm_i915_private *dev_priv,
...@@ -881,11 +937,11 @@ static void skl_set_cdclk(struct drm_i915_private *dev_priv, ...@@ -881,11 +937,11 @@ static void skl_set_cdclk(struct drm_i915_private *dev_priv,
break; break;
} }
if (dev_priv->cdclk_pll.vco != 0 && if (dev_priv->cdclk.hw.vco != 0 &&
dev_priv->cdclk_pll.vco != vco) dev_priv->cdclk.hw.vco != vco)
skl_dpll0_disable(dev_priv); skl_dpll0_disable(dev_priv);
if (dev_priv->cdclk_pll.vco != vco) if (dev_priv->cdclk.hw.vco != vco)
skl_dpll0_enable(dev_priv, vco); skl_dpll0_enable(dev_priv, vco);
I915_WRITE(CDCLK_CTL, freq_select | skl_cdclk_decimal(cdclk)); I915_WRITE(CDCLK_CTL, freq_select | skl_cdclk_decimal(cdclk));
...@@ -913,8 +969,8 @@ static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv) ...@@ -913,8 +969,8 @@ static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
intel_update_cdclk(dev_priv); intel_update_cdclk(dev_priv);
/* Is PLL enabled and locked ? */ /* Is PLL enabled and locked ? */
if (dev_priv->cdclk_pll.vco == 0 || if (dev_priv->cdclk.hw.vco == 0 ||
dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref) dev_priv->cdclk.hw.cdclk == dev_priv->cdclk.hw.ref)
goto sanitize; goto sanitize;
/* DPLL okay; verify the cdclock /* DPLL okay; verify the cdclock
...@@ -925,7 +981,7 @@ static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv) ...@@ -925,7 +981,7 @@ static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
*/ */
cdctl = I915_READ(CDCLK_CTL); cdctl = I915_READ(CDCLK_CTL);
expected = (cdctl & CDCLK_FREQ_SEL_MASK) | expected = (cdctl & CDCLK_FREQ_SEL_MASK) |
skl_cdclk_decimal(dev_priv->cdclk_freq); skl_cdclk_decimal(dev_priv->cdclk.hw.cdclk);
if (cdctl == expected) if (cdctl == expected)
/* All well; nothing to sanitize */ /* All well; nothing to sanitize */
return; return;
...@@ -934,9 +990,9 @@ static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv) ...@@ -934,9 +990,9 @@ static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n"); DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
/* force cdclk programming */ /* force cdclk programming */
dev_priv->cdclk_freq = 0; dev_priv->cdclk.hw.cdclk = 0;
/* force full PLL disable + enable */ /* force full PLL disable + enable */
dev_priv->cdclk_pll.vco = -1; dev_priv->cdclk.hw.vco = -1;
} }
/** /**
...@@ -954,14 +1010,15 @@ void skl_init_cdclk(struct drm_i915_private *dev_priv) ...@@ -954,14 +1010,15 @@ void skl_init_cdclk(struct drm_i915_private *dev_priv)
skl_sanitize_cdclk(dev_priv); skl_sanitize_cdclk(dev_priv);
if (dev_priv->cdclk_freq != 0 && dev_priv->cdclk_pll.vco != 0) { if (dev_priv->cdclk.hw.cdclk != 0 &&
dev_priv->cdclk.hw.vco != 0) {
/* /*
* Use the current vco as our initial * Use the current vco as our initial
* guess as to what the preferred vco is. * guess as to what the preferred vco is.
*/ */
if (dev_priv->skl_preferred_vco_freq == 0) if (dev_priv->skl_preferred_vco_freq == 0)
skl_set_preferred_cdclk_vco(dev_priv, skl_set_preferred_cdclk_vco(dev_priv,
dev_priv->cdclk_pll.vco); dev_priv->cdclk.hw.vco);
return; return;
} }
...@@ -982,7 +1039,7 @@ void skl_init_cdclk(struct drm_i915_private *dev_priv) ...@@ -982,7 +1039,7 @@ void skl_init_cdclk(struct drm_i915_private *dev_priv)
*/ */
void skl_uninit_cdclk(struct drm_i915_private *dev_priv) void skl_uninit_cdclk(struct drm_i915_private *dev_priv)
{ {
skl_set_cdclk(dev_priv, dev_priv->cdclk_pll.ref, 0); skl_set_cdclk(dev_priv, dev_priv->cdclk.hw.ref, 0);
} }
static int bxt_calc_cdclk(int max_pixclk) static int bxt_calc_cdclk(int max_pixclk)
...@@ -1013,7 +1070,7 @@ static int bxt_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk) ...@@ -1013,7 +1070,7 @@ static int bxt_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
{ {
int ratio; int ratio;
if (cdclk == dev_priv->cdclk_pll.ref) if (cdclk == dev_priv->cdclk.hw.ref)
return 0; return 0;
switch (cdclk) { switch (cdclk) {
...@@ -1030,14 +1087,14 @@ static int bxt_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk) ...@@ -1030,14 +1087,14 @@ static int bxt_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
break; break;
} }
return dev_priv->cdclk_pll.ref * ratio; return dev_priv->cdclk.hw.ref * ratio;
} }
static int glk_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk) static int glk_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
{ {
int ratio; int ratio;
if (cdclk == dev_priv->cdclk_pll.ref) if (cdclk == dev_priv->cdclk.hw.ref)
return 0; return 0;
switch (cdclk) { switch (cdclk) {
...@@ -1050,15 +1107,16 @@ static int glk_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk) ...@@ -1050,15 +1107,16 @@ static int glk_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
break; break;
} }
return dev_priv->cdclk_pll.ref * ratio; return dev_priv->cdclk.hw.ref * ratio;
} }
static void bxt_de_pll_update(struct drm_i915_private *dev_priv) static void bxt_de_pll_update(struct drm_i915_private *dev_priv,
struct intel_cdclk_state *cdclk_state)
{ {
u32 val; u32 val;
dev_priv->cdclk_pll.ref = 19200; cdclk_state->ref = 19200;
dev_priv->cdclk_pll.vco = 0; cdclk_state->vco = 0;
val = I915_READ(BXT_DE_PLL_ENABLE); val = I915_READ(BXT_DE_PLL_ENABLE);
if ((val & BXT_DE_PLL_PLL_ENABLE) == 0) if ((val & BXT_DE_PLL_PLL_ENABLE) == 0)
...@@ -1068,20 +1126,21 @@ static void bxt_de_pll_update(struct drm_i915_private *dev_priv) ...@@ -1068,20 +1126,21 @@ static void bxt_de_pll_update(struct drm_i915_private *dev_priv)
return; return;
val = I915_READ(BXT_DE_PLL_CTL); val = I915_READ(BXT_DE_PLL_CTL);
dev_priv->cdclk_pll.vco = (val & BXT_DE_PLL_RATIO_MASK) * cdclk_state->vco = (val & BXT_DE_PLL_RATIO_MASK) * cdclk_state->ref;
dev_priv->cdclk_pll.ref;
} }
static int bxt_get_cdclk(struct drm_i915_private *dev_priv) static void bxt_get_cdclk(struct drm_i915_private *dev_priv,
struct intel_cdclk_state *cdclk_state)
{ {
u32 divider; u32 divider;
int div, vco; int div;
bxt_de_pll_update(dev_priv); bxt_de_pll_update(dev_priv, cdclk_state);
vco = dev_priv->cdclk_pll.vco; cdclk_state->cdclk = cdclk_state->ref;
if (vco == 0)
return dev_priv->cdclk_pll.ref; if (cdclk_state->vco == 0)
return;
divider = I915_READ(CDCLK_CTL) & BXT_CDCLK_CD2X_DIV_SEL_MASK; divider = I915_READ(CDCLK_CTL) & BXT_CDCLK_CD2X_DIV_SEL_MASK;
...@@ -1101,10 +1160,10 @@ static int bxt_get_cdclk(struct drm_i915_private *dev_priv) ...@@ -1101,10 +1160,10 @@ static int bxt_get_cdclk(struct drm_i915_private *dev_priv)
break; break;
default: default:
MISSING_CASE(divider); MISSING_CASE(divider);
return dev_priv->cdclk_pll.ref; return;
} }
return DIV_ROUND_CLOSEST(vco, div); cdclk_state->cdclk = DIV_ROUND_CLOSEST(cdclk_state->vco, div);
} }
static void bxt_de_pll_disable(struct drm_i915_private *dev_priv) static void bxt_de_pll_disable(struct drm_i915_private *dev_priv)
...@@ -1117,12 +1176,12 @@ static void bxt_de_pll_disable(struct drm_i915_private *dev_priv) ...@@ -1117,12 +1176,12 @@ static void bxt_de_pll_disable(struct drm_i915_private *dev_priv)
1)) 1))
DRM_ERROR("timeout waiting for DE PLL unlock\n"); DRM_ERROR("timeout waiting for DE PLL unlock\n");
dev_priv->cdclk_pll.vco = 0; dev_priv->cdclk.hw.vco = 0;
} }
static void bxt_de_pll_enable(struct drm_i915_private *dev_priv, int vco) static void bxt_de_pll_enable(struct drm_i915_private *dev_priv, int vco)
{ {
int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->cdclk_pll.ref); int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->cdclk.hw.ref);
u32 val; u32 val;
val = I915_READ(BXT_DE_PLL_CTL); val = I915_READ(BXT_DE_PLL_CTL);
...@@ -1140,7 +1199,7 @@ static void bxt_de_pll_enable(struct drm_i915_private *dev_priv, int vco) ...@@ -1140,7 +1199,7 @@ static void bxt_de_pll_enable(struct drm_i915_private *dev_priv, int vco)
1)) 1))
DRM_ERROR("timeout waiting for DE PLL lock\n"); DRM_ERROR("timeout waiting for DE PLL lock\n");
dev_priv->cdclk_pll.vco = vco; dev_priv->cdclk.hw.vco = vco;
} }
static void bxt_set_cdclk(struct drm_i915_private *dev_priv, static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
...@@ -1168,7 +1227,7 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv, ...@@ -1168,7 +1227,7 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
divider = BXT_CDCLK_CD2X_DIV_SEL_1; divider = BXT_CDCLK_CD2X_DIV_SEL_1;
break; break;
default: default:
WARN_ON(cdclk != dev_priv->cdclk_pll.ref); WARN_ON(cdclk != dev_priv->cdclk.hw.ref);
WARN_ON(vco != 0); WARN_ON(vco != 0);
divider = BXT_CDCLK_CD2X_DIV_SEL_1; divider = BXT_CDCLK_CD2X_DIV_SEL_1;
...@@ -1187,11 +1246,11 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv, ...@@ -1187,11 +1246,11 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
return; return;
} }
if (dev_priv->cdclk_pll.vco != 0 && if (dev_priv->cdclk.hw.vco != 0 &&
dev_priv->cdclk_pll.vco != vco) dev_priv->cdclk.hw.vco != vco)
bxt_de_pll_disable(dev_priv); bxt_de_pll_disable(dev_priv);
if (dev_priv->cdclk_pll.vco != vco) if (dev_priv->cdclk.hw.vco != vco)
bxt_de_pll_enable(dev_priv, vco); bxt_de_pll_enable(dev_priv, vco);
val = divider | skl_cdclk_decimal(cdclk); val = divider | skl_cdclk_decimal(cdclk);
...@@ -1228,8 +1287,8 @@ static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv) ...@@ -1228,8 +1287,8 @@ static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
intel_update_cdclk(dev_priv); intel_update_cdclk(dev_priv);
if (dev_priv->cdclk_pll.vco == 0 || if (dev_priv->cdclk.hw.vco == 0 ||
dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref) dev_priv->cdclk.hw.cdclk == dev_priv->cdclk.hw.ref)
goto sanitize; goto sanitize;
/* DPLL okay; verify the cdclock /* DPLL okay; verify the cdclock
...@@ -1247,12 +1306,12 @@ static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv) ...@@ -1247,12 +1306,12 @@ static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
cdctl &= ~BXT_CDCLK_CD2X_PIPE_NONE; cdctl &= ~BXT_CDCLK_CD2X_PIPE_NONE;
expected = (cdctl & BXT_CDCLK_CD2X_DIV_SEL_MASK) | expected = (cdctl & BXT_CDCLK_CD2X_DIV_SEL_MASK) |
skl_cdclk_decimal(dev_priv->cdclk_freq); skl_cdclk_decimal(dev_priv->cdclk.hw.cdclk);
/* /*
* Disable SSA Precharge when CD clock frequency < 500 MHz, * Disable SSA Precharge when CD clock frequency < 500 MHz,
* enable otherwise. * enable otherwise.
*/ */
if (dev_priv->cdclk_freq >= 500000) if (dev_priv->cdclk.hw.cdclk >= 500000)
expected |= BXT_CDCLK_SSA_PRECHARGE_ENABLE; expected |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
if (cdctl == expected) if (cdctl == expected)
...@@ -1263,10 +1322,10 @@ static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv) ...@@ -1263,10 +1322,10 @@ static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n"); DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
/* force cdclk programming */ /* force cdclk programming */
dev_priv->cdclk_freq = 0; dev_priv->cdclk.hw.cdclk = 0;
/* force full PLL disable + enable */ /* force full PLL disable + enable */
dev_priv->cdclk_pll.vco = -1; dev_priv->cdclk.hw.vco = -1;
} }
/** /**
...@@ -1284,7 +1343,8 @@ void bxt_init_cdclk(struct drm_i915_private *dev_priv) ...@@ -1284,7 +1343,8 @@ void bxt_init_cdclk(struct drm_i915_private *dev_priv)
bxt_sanitize_cdclk(dev_priv); bxt_sanitize_cdclk(dev_priv);
if (dev_priv->cdclk_freq != 0 && dev_priv->cdclk_pll.vco != 0) if (dev_priv->cdclk.hw.cdclk != 0 &&
dev_priv->cdclk.hw.vco != 0)
return; return;
/* /*
...@@ -1312,7 +1372,21 @@ void bxt_init_cdclk(struct drm_i915_private *dev_priv) ...@@ -1312,7 +1372,21 @@ void bxt_init_cdclk(struct drm_i915_private *dev_priv)
*/ */
void bxt_uninit_cdclk(struct drm_i915_private *dev_priv) void bxt_uninit_cdclk(struct drm_i915_private *dev_priv)
{ {
bxt_set_cdclk(dev_priv, dev_priv->cdclk_pll.ref, 0); bxt_set_cdclk(dev_priv, dev_priv->cdclk.hw.ref, 0);
}
/**
* intel_cdclk_state_compare - Determine if two CDCLK states differ
* @a: first CDCLK state
* @b: second CDCLK state
*
* Returns:
* True if the CDCLK states are identical, false if they differ.
*/
bool intel_cdclk_state_compare(const struct intel_cdclk_state *a,
const struct intel_cdclk_state *b)
{
return memcmp(a, b, sizeof(*a)) == 0;
} }
static int bdw_adjust_min_pipe_pixel_rate(struct intel_crtc_state *crtc_state, static int bdw_adjust_min_pipe_pixel_rate(struct intel_crtc_state *crtc_state,
...@@ -1620,7 +1694,7 @@ void intel_update_max_cdclk(struct drm_i915_private *dev_priv) ...@@ -1620,7 +1694,7 @@ void intel_update_max_cdclk(struct drm_i915_private *dev_priv)
dev_priv->max_cdclk_freq = 400000; dev_priv->max_cdclk_freq = 400000;
} else { } else {
/* otherwise assume cdclk is fixed */ /* otherwise assume cdclk is fixed */
dev_priv->max_cdclk_freq = dev_priv->cdclk_freq; dev_priv->max_cdclk_freq = dev_priv->cdclk.hw.cdclk;
} }
dev_priv->max_dotclk_freq = intel_compute_max_dotclk(dev_priv); dev_priv->max_dotclk_freq = intel_compute_max_dotclk(dev_priv);
...@@ -1640,15 +1714,11 @@ void intel_update_max_cdclk(struct drm_i915_private *dev_priv) ...@@ -1640,15 +1714,11 @@ void intel_update_max_cdclk(struct drm_i915_private *dev_priv)
*/ */
void intel_update_cdclk(struct drm_i915_private *dev_priv) void intel_update_cdclk(struct drm_i915_private *dev_priv)
{ {
dev_priv->cdclk_freq = dev_priv->display.get_cdclk(dev_priv); dev_priv->display.get_cdclk(dev_priv, &dev_priv->cdclk.hw);
if (INTEL_GEN(dev_priv) >= 9) DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz, VCO: %d kHz, ref: %d kHz\n",
DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz, VCO: %d kHz, ref: %d kHz\n", dev_priv->cdclk.hw.cdclk, dev_priv->cdclk.hw.vco,
dev_priv->cdclk_freq, dev_priv->cdclk_pll.vco, dev_priv->cdclk.hw.ref);
dev_priv->cdclk_pll.ref);
else
DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz\n",
dev_priv->cdclk_freq);
/* /*
* 9:0 CMBUS [sic] CDCLK frequency (cdfreq): * 9:0 CMBUS [sic] CDCLK frequency (cdfreq):
...@@ -1658,7 +1728,7 @@ void intel_update_cdclk(struct drm_i915_private *dev_priv) ...@@ -1658,7 +1728,7 @@ void intel_update_cdclk(struct drm_i915_private *dev_priv)
*/ */
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
I915_WRITE(GMBUSFREQ_VLV, I915_WRITE(GMBUSFREQ_VLV,
DIV_ROUND_UP(dev_priv->cdclk_freq, 1000)); DIV_ROUND_UP(dev_priv->cdclk.hw.cdclk, 1000));
} }
static int pch_rawclk(struct drm_i915_private *dev_priv) static int pch_rawclk(struct drm_i915_private *dev_priv)
......
...@@ -135,7 +135,7 @@ struct intel_limit { ...@@ -135,7 +135,7 @@ struct intel_limit {
}; };
/* returns HPLL frequency in kHz */ /* returns HPLL frequency in kHz */
static int valleyview_get_vco(struct drm_i915_private *dev_priv) int vlv_get_hpll_vco(struct drm_i915_private *dev_priv)
{ {
int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 }; int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 };
...@@ -171,7 +171,7 @@ int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv, ...@@ -171,7 +171,7 @@ int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
const char *name, u32 reg) const char *name, u32 reg)
{ {
if (dev_priv->hpll_freq == 0) if (dev_priv->hpll_freq == 0)
dev_priv->hpll_freq = valleyview_get_vco(dev_priv); dev_priv->hpll_freq = vlv_get_hpll_vco(dev_priv);
return vlv_get_cck_clock(dev_priv, name, reg, return vlv_get_cck_clock(dev_priv, name, reg,
dev_priv->hpll_freq); dev_priv->hpll_freq);
...@@ -12413,7 +12413,7 @@ static int intel_modeset_checks(struct drm_atomic_state *state) ...@@ -12413,7 +12413,7 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
*/ */
if (dev_priv->display.modeset_calc_cdclk) { if (dev_priv->display.modeset_calc_cdclk) {
if (!intel_state->cdclk_pll_vco) if (!intel_state->cdclk_pll_vco)
intel_state->cdclk_pll_vco = dev_priv->cdclk_pll.vco; intel_state->cdclk_pll_vco = dev_priv->cdclk.hw.vco;
if (!intel_state->cdclk_pll_vco) if (!intel_state->cdclk_pll_vco)
intel_state->cdclk_pll_vco = dev_priv->skl_preferred_vco_freq; intel_state->cdclk_pll_vco = dev_priv->skl_preferred_vco_freq;
...@@ -12433,8 +12433,8 @@ static int intel_modeset_checks(struct drm_atomic_state *state) ...@@ -12433,8 +12433,8 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
} }
/* All pipes must be switched off while we change the cdclk. */ /* All pipes must be switched off while we change the cdclk. */
if (intel_state->dev_cdclk != dev_priv->cdclk_freq || if (intel_state->dev_cdclk != dev_priv->cdclk.hw.cdclk ||
intel_state->cdclk_pll_vco != dev_priv->cdclk_pll.vco) { intel_state->cdclk_pll_vco != dev_priv->cdclk.hw.vco) {
ret = intel_modeset_all_pipes(state); ret = intel_modeset_all_pipes(state);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -12869,8 +12869,8 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) ...@@ -12869,8 +12869,8 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
drm_atomic_helper_update_legacy_modeset_state(state->dev, state); drm_atomic_helper_update_legacy_modeset_state(state->dev, state);
if (dev_priv->display.modeset_commit_cdclk && if (dev_priv->display.modeset_commit_cdclk &&
(intel_state->dev_cdclk != dev_priv->cdclk_freq || (intel_state->dev_cdclk != dev_priv->cdclk.hw.cdclk ||
intel_state->cdclk_pll_vco != dev_priv->cdclk_pll.vco)) intel_state->cdclk_pll_vco != dev_priv->cdclk.hw.vco))
dev_priv->display.modeset_commit_cdclk(state); dev_priv->display.modeset_commit_cdclk(state);
/* /*
...@@ -14855,7 +14855,7 @@ void intel_modeset_init_hw(struct drm_device *dev) ...@@ -14855,7 +14855,7 @@ void intel_modeset_init_hw(struct drm_device *dev)
intel_update_cdclk(dev_priv); intel_update_cdclk(dev_priv);
dev_priv->atomic_cdclk_freq = dev_priv->cdclk_freq; dev_priv->atomic_cdclk_freq = dev_priv->cdclk.hw.cdclk;
intel_init_clock_gating(dev_priv); intel_init_clock_gating(dev_priv);
} }
...@@ -15031,7 +15031,7 @@ int intel_modeset_init(struct drm_device *dev) ...@@ -15031,7 +15031,7 @@ int intel_modeset_init(struct drm_device *dev)
intel_update_czclk(dev_priv); intel_update_czclk(dev_priv);
intel_update_cdclk(dev_priv); intel_update_cdclk(dev_priv);
dev_priv->atomic_cdclk_freq = dev_priv->cdclk_freq; dev_priv->atomic_cdclk_freq = dev_priv->cdclk.hw.cdclk;
intel_shared_dpll_init(dev); intel_shared_dpll_init(dev);
......
...@@ -918,7 +918,7 @@ static uint32_t ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index) ...@@ -918,7 +918,7 @@ static uint32_t ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
* divide by 2000 and use that * divide by 2000 and use that
*/ */
if (intel_dig_port->port == PORT_A) if (intel_dig_port->port == PORT_A)
return DIV_ROUND_CLOSEST(dev_priv->cdclk_freq, 2000); return DIV_ROUND_CLOSEST(dev_priv->cdclk.hw.cdclk, 2000);
else else
return DIV_ROUND_CLOSEST(dev_priv->rawclk_freq, 2000); return DIV_ROUND_CLOSEST(dev_priv->rawclk_freq, 2000);
} }
......
...@@ -1251,10 +1251,13 @@ void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv); ...@@ -1251,10 +1251,13 @@ void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv);
void intel_update_max_cdclk(struct drm_i915_private *dev_priv); void intel_update_max_cdclk(struct drm_i915_private *dev_priv);
void intel_update_cdclk(struct drm_i915_private *dev_priv); void intel_update_cdclk(struct drm_i915_private *dev_priv);
void intel_update_rawclk(struct drm_i915_private *dev_priv); void intel_update_rawclk(struct drm_i915_private *dev_priv);
bool intel_cdclk_state_compare(const struct intel_cdclk_state *a,
const struct intel_cdclk_state *b);
/* intel_display.c */ /* intel_display.c */
enum transcoder intel_crtc_pch_transcoder(struct intel_crtc *crtc); enum transcoder intel_crtc_pch_transcoder(struct intel_crtc *crtc);
void intel_update_rawclk(struct drm_i915_private *dev_priv); void intel_update_rawclk(struct drm_i915_private *dev_priv);
int vlv_get_hpll_vco(struct drm_i915_private *dev_priv);
int vlv_get_cck_clock(struct drm_i915_private *dev_priv, int vlv_get_cck_clock(struct drm_i915_private *dev_priv,
const char *name, u32 reg, int ref_freq); const char *name, u32 reg, int ref_freq);
int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv, int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
......
...@@ -817,7 +817,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) ...@@ -817,7 +817,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
/* WaFbcExceedCdClockThreshold:hsw,bdw */ /* WaFbcExceedCdClockThreshold:hsw,bdw */
if ((IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) && if ((IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) &&
cache->crtc.hsw_bdw_pixel_rate >= dev_priv->cdclk_freq * 95 / 100) { cache->crtc.hsw_bdw_pixel_rate >= dev_priv->cdclk.hw.cdclk * 95 / 100) {
fbc->no_fbc_reason = "pixel rate is too big"; fbc->no_fbc_reason = "pixel rate is too big";
return false; return false;
} }
......
...@@ -1315,7 +1315,7 @@ static u32 i9xx_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) ...@@ -1315,7 +1315,7 @@ static u32 i9xx_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
if (IS_PINEVIEW(dev_priv)) if (IS_PINEVIEW(dev_priv))
clock = KHz(dev_priv->rawclk_freq); clock = KHz(dev_priv->rawclk_freq);
else else
clock = KHz(dev_priv->cdclk_freq); clock = KHz(dev_priv->cdclk.hw.cdclk);
return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 32); return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 32);
} }
...@@ -1333,7 +1333,7 @@ static u32 i965_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) ...@@ -1333,7 +1333,7 @@ static u32 i965_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
if (IS_G4X(dev_priv)) if (IS_G4X(dev_priv))
clock = KHz(dev_priv->rawclk_freq); clock = KHz(dev_priv->rawclk_freq);
else else
clock = KHz(dev_priv->cdclk_freq); clock = KHz(dev_priv->cdclk.hw.cdclk);
return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 128); return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 128);
} }
......
...@@ -964,9 +964,12 @@ static void gen9_assert_dbuf_enabled(struct drm_i915_private *dev_priv) ...@@ -964,9 +964,12 @@ static void gen9_assert_dbuf_enabled(struct drm_i915_private *dev_priv)
static void gen9_dc_off_power_well_enable(struct drm_i915_private *dev_priv, static void gen9_dc_off_power_well_enable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well) struct i915_power_well *power_well)
{ {
struct intel_cdclk_state cdclk_state = {};
gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
WARN_ON(dev_priv->cdclk_freq != dev_priv->display.get_cdclk(dev_priv)); dev_priv->display.get_cdclk(dev_priv, &cdclk_state);
WARN_ON(!intel_cdclk_state_compare(&dev_priv->cdclk.hw, &cdclk_state));
gen9_assert_dbuf_enabled(dev_priv); gen9_assert_dbuf_enabled(dev_priv);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment