summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c2
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h14
-rw-r--r--drivers/gpu/drm/i915/intel_audio.c2
-rw-r--r--drivers/gpu/drm/i915/intel_cdclk.c382
-rw-r--r--drivers/gpu/drm/i915/intel_display.c18
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c2
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h3
-rw-r--r--drivers/gpu/drm/i915/intel_fbc.c2
-rw-r--r--drivers/gpu/drm/i915/intel_panel.c4
-rw-r--r--drivers/gpu/drm/i915/intel_runtime_pm.c5
10 files changed, 258 insertions, 176 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 6400f83d3ad1..1ccc2978a21a 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -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_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 pixel clock frequency: %d kHz\n", dev_priv->max_dotclk_freq);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index f41496405484..aa59b2153374 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -600,9 +600,11 @@ struct intel_initial_plane_config;
struct intel_crtc;
struct intel_limit;
struct dpll;
+struct intel_cdclk_state;
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 (*compute_pipe_wm)(struct intel_crtc_state *cstate);
int (*compute_intermediate_wm)(struct drm_device *dev,
@@ -2060,6 +2062,10 @@ struct i915_oa_ops {
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_device drm;
@@ -2164,7 +2170,7 @@ struct drm_i915_private {
unsigned int fsb_freq, mem_freq, is_ddr3;
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,
@@ -2178,8 +2184,8 @@ struct drm_i915_private {
unsigned int czclk_freq;
struct {
- unsigned int vco, ref;
- } cdclk_pll;
+ struct intel_cdclk_state hw;
+ } cdclk;
/**
* wq - Driver workqueue for GEM.
diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c
index cd9d20763140..1ab401faed34 100644
--- a/drivers/gpu/drm/i915/intel_audio.c
+++ b/drivers/gpu/drm/i915/intel_audio.c
@@ -734,7 +734,7 @@ static int i915_audio_component_get_cdclk_freq(struct device *kdev)
if (WARN_ON_ONCE(!HAS_DDI(dev_priv)))
return -ENODEV;
- return dev_priv->cdclk_freq;
+ return dev_priv->cdclk.hw.cdclk;
}
/*
diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c
index a0736b5f2d47..4e74e87a8676 100644
--- a/drivers/gpu/drm/i915/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/intel_cdclk.c
@@ -51,37 +51,44 @@
* 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;
u16 hpllcc = 0;
@@ -91,8 +98,10 @@ static int i85x_get_cdclk(struct drm_i915_private *dev_priv)
* encoding is different :(
* FIXME is this the right way to detect 852GM/852GMV?
*/
- if (pdev->revision == 0x1)
- return 133333;
+ if (pdev->revision == 0x1) {
+ cdclk_state->cdclk = 133333;
+ return;
+ }
pci_bus_read_config_word(pdev->bus,
PCI_DEVFN(0, 3), HPLLCC, &hpllcc);
@@ -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_2:
case GC_CLOCK_100_200:
- return 200000;
+ cdclk_state->cdclk = 200000;
+ break;
case GC_CLOCK_166_250:
- return 250000;
+ cdclk_state->cdclk = 250000;
+ break;
case GC_CLOCK_100_133:
- return 133333;
+ cdclk_state->cdclk = 133333;
+ break;
case GC_CLOCK_133_266:
case GC_CLOCK_133_266_2:
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;
u16 gcfgc = 0;
pci_read_config_word(pdev, GCFGC, &gcfgc);
- if (gcfgc & GC_LOW_FREQUENCY_ENABLE)
- return 133333;
+ if (gcfgc & GC_LOW_FREQUENCY_ENABLE) {
+ cdclk_state->cdclk = 133333;
+ return;
+ }
switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
case GC_DISPLAY_CLOCK_333_320_MHZ:
- return 333333;
+ cdclk_state->cdclk = 333333;
+ break;
default:
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;
u16 gcfgc = 0;
pci_read_config_word(pdev, GCFGC, &gcfgc);
- if (gcfgc & GC_LOW_FREQUENCY_ENABLE)
- return 133333;
+ if (gcfgc & GC_LOW_FREQUENCY_ENABLE) {
+ cdclk_state->cdclk = 133333;
+ return;
+ }
switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
case GC_DISPLAY_CLOCK_333_320_MHZ:
- return 320000;
+ cdclk_state->cdclk = 320000;
+ break;
default:
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)
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;
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)
static const uint8_t div_4800[] = { 20, 14, 12, 10, 8, 24 };
static const uint8_t div_5333[] = { 20, 16, 12, 12, 8, 28 };
const uint8_t *div_table;
- unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
+ unsigned int cdclk_sel;
uint16_t tmp = 0;
+ cdclk_state->vco = intel_hpll_vco(dev_priv);
+
pci_read_config_word(pdev, GCFGC, &tmp);
cdclk_sel = (tmp >> 4) & 0x7;
@@ -243,7 +266,7 @@ static int g33_get_cdclk(struct drm_i915_private *dev_priv)
if (cdclk_sel >= ARRAY_SIZE(div_3200))
goto fail;
- switch (vco) {
+ switch (cdclk_state->vco) {
case 3200000:
div_table = div_3200;
break;
@@ -260,15 +283,18 @@ static int g33_get_cdclk(struct drm_i915_private *dev_priv)
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:
DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz, CFGC=0x%08x\n",
- vco, tmp);
- return 190476;
+ cdclk_state->vco, tmp);
+ 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;
u16 gcfgc = 0;
@@ -277,32 +303,41 @@ static int pnv_get_cdclk(struct drm_i915_private *dev_priv)
switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
case GC_DISPLAY_CLOCK_267_MHZ_PNV:
- return 266667;
+ cdclk_state->cdclk = 266667;
+ break;
case GC_DISPLAY_CLOCK_333_MHZ_PNV:
- return 333333;
+ cdclk_state->cdclk = 333333;
+ break;
case GC_DISPLAY_CLOCK_444_MHZ_PNV:
- return 444444;
+ cdclk_state->cdclk = 444444;
+ break;
case GC_DISPLAY_CLOCK_200_MHZ_PNV:
- return 200000;
+ cdclk_state->cdclk = 200000;
+ break;
default:
DRM_ERROR("Unknown pnv display core clock 0x%04x\n", gcfgc);
case GC_DISPLAY_CLOCK_133_MHZ_PNV:
- return 133333;
+ cdclk_state->cdclk = 133333;
+ break;
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;
static const uint8_t div_3200[] = { 16, 10, 8 };
static const uint8_t div_4000[] = { 20, 12, 10 };
static const uint8_t div_5333[] = { 24, 16, 14 };
const uint8_t *div_table;
- unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
+ unsigned int cdclk_sel;
uint16_t tmp = 0;
+ cdclk_state->vco = intel_hpll_vco(dev_priv);
+
pci_read_config_word(pdev, GCFGC, &tmp);
cdclk_sel = ((tmp >> 8) & 0x1f) - 1;
@@ -310,7 +345,7 @@ static int i965gm_get_cdclk(struct drm_i915_private *dev_priv)
if (cdclk_sel >= ARRAY_SIZE(div_3200))
goto fail;
- switch (vco) {
+ switch (cdclk_state->vco) {
case 3200000:
div_table = div_3200;
break;
@@ -324,53 +359,62 @@ static int i965gm_get_cdclk(struct drm_i915_private *dev_priv)
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:
DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz, CFGC=0x%04x\n",
- vco, tmp);
- return 200000;
+ cdclk_state->vco, tmp);
+ 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;
- unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
+ unsigned int cdclk_sel;
uint16_t tmp = 0;
+ cdclk_state->vco = intel_hpll_vco(dev_priv);
+
pci_read_config_word(pdev, GCFGC, &tmp);
cdclk_sel = (tmp >> 12) & 0x1;
- switch (vco) {
+ switch (cdclk_state->vco) {
case 2666667:
case 4000000:
case 5333333:
- return cdclk_sel ? 333333 : 222222;
+ cdclk_state->cdclk = cdclk_sel ? 333333 : 222222;
+ break;
case 3200000:
- return cdclk_sel ? 320000 : 228571;
+ cdclk_state->cdclk = cdclk_sel ? 320000 : 228571;
+ break;
default:
DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u, CFGC=0x%04x\n",
- vco, tmp);
- return 222222;
+ cdclk_state->vco, tmp);
+ 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 freq = lcpll & LCPLL_CLK_FREQ_MASK;
if (lcpll & LCPLL_CD_SOURCE_FCLK)
- return 800000;
+ cdclk_state->cdclk = 800000;
else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
- return 450000;
+ cdclk_state->cdclk = 450000;
else if (freq == LCPLL_CLK_FREQ_450)
- return 450000;
+ cdclk_state->cdclk = 450000;
else if (IS_HSW_ULT(dev_priv))
- return 337500;
+ cdclk_state->cdclk = 337500;
else
- return 540000;
+ cdclk_state->cdclk = 540000;
}
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;
}
-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",
- CCK_DISPLAY_CLOCK_CONTROL);
+ cdclk_state->vco = vlv_get_hpll_vco(dev_priv);
+ 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)
@@ -411,7 +458,7 @@ static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv)
else
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 */
if (IS_CHERRYVIEW(dev_priv))
credits = PFI_CREDIT_63;
@@ -443,8 +490,6 @@ static void vlv_set_cdclk(struct drm_device *dev, int cdclk)
struct drm_i915_private *dev_priv = to_i915(dev);
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 */
cmd = 2;
else if (cdclk == 266667)
@@ -508,8 +553,6 @@ static void chv_set_cdclk(struct drm_device *dev, int cdclk)
struct drm_i915_private *dev_priv = to_i915(dev);
u32 val, cmd;
- WARN_ON(dev_priv->display.get_cdclk(dev_priv) != dev_priv->cdclk_freq);
-
switch (cdclk) {
case 333333:
case 320000:
@@ -555,23 +598,24 @@ static int bdw_calc_cdclk(int max_pixclk)
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 freq = lcpll & LCPLL_CLK_FREQ_MASK;
if (lcpll & LCPLL_CD_SOURCE_FCLK)
- return 800000;
+ cdclk_state->cdclk = 800000;
else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
- return 450000;
+ cdclk_state->cdclk = 450000;
else if (freq == LCPLL_CLK_FREQ_450)
- return 450000;
+ cdclk_state->cdclk = 450000;
else if (freq == LCPLL_CLK_FREQ_54O_BDW)
- return 540000;
+ cdclk_state->cdclk = 540000;
else if (freq == LCPLL_CLK_FREQ_337_5_BDW)
- return 337500;
+ cdclk_state->cdclk = 337500;
else
- return 675000;
+ cdclk_state->cdclk = 675000;
}
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);
- WARN(cdclk != dev_priv->cdclk_freq,
+ WARN(cdclk != dev_priv->cdclk.hw.cdclk,
"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)
@@ -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;
- dev_priv->cdclk_pll.ref = 24000;
- dev_priv->cdclk_pll.vco = 0;
+ cdclk_state->ref = 24000;
+ cdclk_state->vco = 0;
val = I915_READ(LCPLL1_CTL);
if ((val & LCPLL_PLL_ENABLE) == 0)
@@ -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_1620, 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;
case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, 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;
default:
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)
}
}
-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;
- skl_dpll0_update(dev_priv);
+ skl_dpll0_update(dev_priv, cdclk_state);
- if (dev_priv->cdclk_pll.vco == 0)
- return dev_priv->cdclk_pll.ref;
+ cdclk_state->cdclk = cdclk_state->ref;
+
+ if (cdclk_state->vco == 0)
+ return;
cdctl = I915_READ(CDCLK_CTL);
- if (dev_priv->cdclk_pll.vco == 8640000) {
+ if (cdclk_state->vco == 8640000) {
switch (cdctl & CDCLK_FREQ_SEL_MASK) {
case CDCLK_FREQ_450_432:
- return 432000;
+ cdclk_state->cdclk = 432000;
+ break;
case CDCLK_FREQ_337_308:
- return 308571;
+ cdclk_state->cdclk = 308571;
+ break;
case CDCLK_FREQ_540:
- return 540000;
+ cdclk_state->cdclk = 540000;
+ break;
case CDCLK_FREQ_675_617:
- return 617143;
+ cdclk_state->cdclk = 617143;
+ break;
default:
MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
+ break;
}
} else {
switch (cdctl & CDCLK_FREQ_SEL_MASK) {
case CDCLK_FREQ_450_432:
- return 450000;
+ cdclk_state->cdclk = 450000;
+ break;
case CDCLK_FREQ_337_308:
- return 337500;
+ cdclk_state->cdclk = 337500;
+ break;
case CDCLK_FREQ_540:
- return 540000;
+ cdclk_state->cdclk = 540000;
+ break;
case CDCLK_FREQ_675_617:
- return 675000;
+ cdclk_state->cdclk = 675000;
+ break;
default:
MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
+ break;
}
}
-
- return dev_priv->cdclk_pll.ref;
}
/* 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)
5))
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. */
skl_set_preferred_cdclk_vco(dev_priv, vco);
@@ -831,7 +887,7 @@ static void skl_dpll0_disable(struct drm_i915_private *dev_priv)
1))
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,
@@ -881,11 +937,11 @@ static void skl_set_cdclk(struct drm_i915_private *dev_priv,
break;
}
- if (dev_priv->cdclk_pll.vco != 0 &&
- dev_priv->cdclk_pll.vco != vco)
+ if (dev_priv->cdclk.hw.vco != 0 &&
+ dev_priv->cdclk.hw.vco != vco)
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);
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)
intel_update_cdclk(dev_priv);
/* Is PLL enabled and locked ? */
- if (dev_priv->cdclk_pll.vco == 0 ||
- dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
+ if (dev_priv->cdclk.hw.vco == 0 ||
+ dev_priv->cdclk.hw.cdclk == dev_priv->cdclk.hw.ref)
goto sanitize;
/* DPLL okay; verify the cdclock
@@ -925,7 +981,7 @@ static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
*/
cdctl = I915_READ(CDCLK_CTL);
expected = (cdctl & CDCLK_FREQ_SEL_MASK) |
- skl_cdclk_decimal(dev_priv->cdclk_freq);
+ skl_cdclk_decimal(dev_priv->cdclk.hw.cdclk);
if (cdctl == expected)
/* All well; nothing to sanitize */
return;
@@ -934,9 +990,9 @@ sanitize:
DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
/* force cdclk programming */
- dev_priv->cdclk_freq = 0;
+ dev_priv->cdclk.hw.cdclk = 0;
/* 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)
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
* guess as to what the preferred vco is.
*/
if (dev_priv->skl_preferred_vco_freq == 0)
skl_set_preferred_cdclk_vco(dev_priv,
- dev_priv->cdclk_pll.vco);
+ dev_priv->cdclk.hw.vco);
return;
}
@@ -982,7 +1039,7 @@ void skl_init_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)
@@ -1013,7 +1070,7 @@ static int bxt_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
{
int ratio;
- if (cdclk == dev_priv->cdclk_pll.ref)
+ if (cdclk == dev_priv->cdclk.hw.ref)
return 0;
switch (cdclk) {
@@ -1030,14 +1087,14 @@ static int bxt_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
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)
{
int ratio;
- if (cdclk == dev_priv->cdclk_pll.ref)
+ if (cdclk == dev_priv->cdclk.hw.ref)
return 0;
switch (cdclk) {
@@ -1050,15 +1107,16 @@ static int glk_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
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;
- dev_priv->cdclk_pll.ref = 19200;
- dev_priv->cdclk_pll.vco = 0;
+ cdclk_state->ref = 19200;
+ cdclk_state->vco = 0;
val = I915_READ(BXT_DE_PLL_ENABLE);
if ((val & BXT_DE_PLL_PLL_ENABLE) == 0)
@@ -1068,20 +1126,21 @@ static void bxt_de_pll_update(struct drm_i915_private *dev_priv)
return;
val = I915_READ(BXT_DE_PLL_CTL);
- dev_priv->cdclk_pll.vco = (val & BXT_DE_PLL_RATIO_MASK) *
- dev_priv->cdclk_pll.ref;
+ cdclk_state->vco = (val & BXT_DE_PLL_RATIO_MASK) * cdclk_state->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;
- 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;
- if (vco == 0)
- return dev_priv->cdclk_pll.ref;
+ cdclk_state->cdclk = cdclk_state->ref;
+
+ if (cdclk_state->vco == 0)
+ return;
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)
break;
default:
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)
@@ -1117,12 +1176,12 @@ static void bxt_de_pll_disable(struct drm_i915_private *dev_priv)
1))
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)
{
- int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->cdclk_pll.ref);
+ int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->cdclk.hw.ref);
u32 val;
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)
1))
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,
@@ -1168,7 +1227,7 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
divider = BXT_CDCLK_CD2X_DIV_SEL_1;
break;
default:
- WARN_ON(cdclk != dev_priv->cdclk_pll.ref);
+ WARN_ON(cdclk != dev_priv->cdclk.hw.ref);
WARN_ON(vco != 0);
divider = BXT_CDCLK_CD2X_DIV_SEL_1;
@@ -1187,11 +1246,11 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
return;
}
- if (dev_priv->cdclk_pll.vco != 0 &&
- dev_priv->cdclk_pll.vco != vco)
+ if (dev_priv->cdclk.hw.vco != 0 &&
+ dev_priv->cdclk.hw.vco != vco)
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);
val = divider | skl_cdclk_decimal(cdclk);
@@ -1228,8 +1287,8 @@ static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
intel_update_cdclk(dev_priv);
- if (dev_priv->cdclk_pll.vco == 0 ||
- dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
+ if (dev_priv->cdclk.hw.vco == 0 ||
+ dev_priv->cdclk.hw.cdclk == dev_priv->cdclk.hw.ref)
goto sanitize;
/* DPLL okay; verify the cdclock
@@ -1247,12 +1306,12 @@ static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
cdctl &= ~BXT_CDCLK_CD2X_PIPE_NONE;
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,
* enable otherwise.
*/
- if (dev_priv->cdclk_freq >= 500000)
+ if (dev_priv->cdclk.hw.cdclk >= 500000)
expected |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
if (cdctl == expected)
@@ -1263,10 +1322,10 @@ sanitize:
DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
/* force cdclk programming */
- dev_priv->cdclk_freq = 0;
+ dev_priv->cdclk.hw.cdclk = 0;
/* 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)
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;
/*
@@ -1312,7 +1372,21 @@ void bxt_init_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,
@@ -1620,7 +1694,7 @@ void intel_update_max_cdclk(struct drm_i915_private *dev_priv)
dev_priv->max_cdclk_freq = 400000;
} else {
/* 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);
@@ -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)
{
- 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",
- dev_priv->cdclk_freq, dev_priv->cdclk_pll.vco,
- dev_priv->cdclk_pll.ref);
- else
- DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz\n",
- dev_priv->cdclk_freq);
+ 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.hw.ref);
/*
* 9:0 CMBUS [sic] CDCLK frequency (cdfreq):
@@ -1658,7 +1728,7 @@ void intel_update_cdclk(struct drm_i915_private *dev_priv)
*/
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
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)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index e996f8ec8f08..691db36d8388 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -135,7 +135,7 @@ struct intel_limit {
};
/* 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 };
@@ -171,7 +171,7 @@ int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
const char *name, u32 reg)
{
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,
dev_priv->hpll_freq);
@@ -12413,7 +12413,7 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
*/
if (dev_priv->display.modeset_calc_cdclk) {
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)
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)
}
/* All pipes must be switched off while we change the cdclk. */
- if (intel_state->dev_cdclk != dev_priv->cdclk_freq ||
- intel_state->cdclk_pll_vco != dev_priv->cdclk_pll.vco) {
+ if (intel_state->dev_cdclk != dev_priv->cdclk.hw.cdclk ||
+ intel_state->cdclk_pll_vco != dev_priv->cdclk.hw.vco) {
ret = intel_modeset_all_pipes(state);
if (ret < 0)
return ret;
@@ -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);
if (dev_priv->display.modeset_commit_cdclk &&
- (intel_state->dev_cdclk != dev_priv->cdclk_freq ||
- intel_state->cdclk_pll_vco != dev_priv->cdclk_pll.vco))
+ (intel_state->dev_cdclk != dev_priv->cdclk.hw.cdclk ||
+ intel_state->cdclk_pll_vco != dev_priv->cdclk.hw.vco))
dev_priv->display.modeset_commit_cdclk(state);
/*
@@ -14855,7 +14855,7 @@ void intel_modeset_init_hw(struct drm_device *dev)
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);
}
@@ -15031,7 +15031,7 @@ int intel_modeset_init(struct drm_device *dev)
intel_update_czclk(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);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 21924cf4c8ad..f8c23fed4a2c 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -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
*/
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
return DIV_ROUND_CLOSEST(dev_priv->rawclk_freq, 2000);
}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 4bdb1f3cb0b5..ba0728ccff75 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -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_cdclk(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 */
enum transcoder intel_crtc_pch_transcoder(struct intel_crtc *crtc);
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,
const char *name, u32 reg, int ref_freq);
int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index c66ba7e36289..22c56ae086f2 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -817,7 +817,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
/* WaFbcExceedCdClockThreshold:hsw,bdw */
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";
return false;
}
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index 1a6ff26dea20..cb50c527401f 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -1315,7 +1315,7 @@ static u32 i9xx_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
if (IS_PINEVIEW(dev_priv))
clock = KHz(dev_priv->rawclk_freq);
else
- clock = KHz(dev_priv->cdclk_freq);
+ clock = KHz(dev_priv->cdclk.hw.cdclk);
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)
if (IS_G4X(dev_priv))
clock = KHz(dev_priv->rawclk_freq);
else
- clock = KHz(dev_priv->cdclk_freq);
+ clock = KHz(dev_priv->cdclk.hw.cdclk);
return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 128);
}
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index 915914f9444c..0f00a5aab69c 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -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,
struct i915_power_well *power_well)
{
+ struct intel_cdclk_state cdclk_state = {};
+
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);