mirror of https://gitee.com/openkylin/linux.git
drm/i915: vlv: cache current CD clock rate
Instead of reading out the CD clock rate from the HW at each modeset, do this only during driver init and resume and use the cached value during modeset. This moves things towards a state where the sw and hw side setup is separated. It's also needed for VLV RPM, where we don't put device into D0 state until modeset_global_resources is called and thus can't access any display/gfx registers. Signed-off-by: Imre Deak <imre.deak@intel.com> Reviewed-by: Antti Koskipää <antti.koskipaa@linux.intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
parent
0d8f94912a
commit
d60c4473b6
|
@ -1339,6 +1339,7 @@ typedef struct drm_i915_private {
|
||||||
int num_fence_regs; /* 8 on pre-965, 16 otherwise */
|
int num_fence_regs; /* 8 on pre-965, 16 otherwise */
|
||||||
|
|
||||||
unsigned int fsb_freq, mem_freq, is_ddr3;
|
unsigned int fsb_freq, mem_freq, is_ddr3;
|
||||||
|
unsigned int vlv_cdclk_freq;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wq - Driver workqueue for GEM.
|
* wq - Driver workqueue for GEM.
|
||||||
|
|
|
@ -4201,6 +4201,9 @@ static void valleyview_set_cdclk(struct drm_device *dev, int cdclk)
|
||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
u32 val, cmd;
|
u32 val, cmd;
|
||||||
|
|
||||||
|
WARN_ON(valleyview_cur_cdclk(dev_priv) != dev_priv->vlv_cdclk_freq);
|
||||||
|
dev_priv->vlv_cdclk_freq = cdclk;
|
||||||
|
|
||||||
if (cdclk >= 320) /* jump to highest voltage for 400MHz too */
|
if (cdclk >= 320) /* jump to highest voltage for 400MHz too */
|
||||||
cmd = 2;
|
cmd = 2;
|
||||||
else if (cdclk == 266)
|
else if (cdclk == 266)
|
||||||
|
@ -4255,7 +4258,7 @@ static void valleyview_set_cdclk(struct drm_device *dev, int cdclk)
|
||||||
intel_i2c_reset(dev);
|
intel_i2c_reset(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int valleyview_cur_cdclk(struct drm_i915_private *dev_priv)
|
int valleyview_cur_cdclk(struct drm_i915_private *dev_priv)
|
||||||
{
|
{
|
||||||
int cur_cdclk, vco;
|
int cur_cdclk, vco;
|
||||||
int divider;
|
int divider;
|
||||||
|
@ -4276,10 +4279,6 @@ static int valleyview_cur_cdclk(struct drm_i915_private *dev_priv)
|
||||||
static int valleyview_calc_cdclk(struct drm_i915_private *dev_priv,
|
static int valleyview_calc_cdclk(struct drm_i915_private *dev_priv,
|
||||||
int max_pixclk)
|
int max_pixclk)
|
||||||
{
|
{
|
||||||
int cur_cdclk;
|
|
||||||
|
|
||||||
cur_cdclk = valleyview_cur_cdclk(dev_priv);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Really only a few cases to deal with, as only 4 CDclks are supported:
|
* Really only a few cases to deal with, as only 4 CDclks are supported:
|
||||||
* 200MHz
|
* 200MHz
|
||||||
|
@ -4321,9 +4320,9 @@ static void valleyview_modeset_global_pipes(struct drm_device *dev,
|
||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
struct intel_crtc *intel_crtc;
|
struct intel_crtc *intel_crtc;
|
||||||
int max_pixclk = intel_mode_max_pixclk(dev_priv);
|
int max_pixclk = intel_mode_max_pixclk(dev_priv);
|
||||||
int cur_cdclk = valleyview_cur_cdclk(dev_priv);
|
|
||||||
|
|
||||||
if (valleyview_calc_cdclk(dev_priv, max_pixclk) == cur_cdclk)
|
if (valleyview_calc_cdclk(dev_priv, max_pixclk) ==
|
||||||
|
dev_priv->vlv_cdclk_freq)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* disable/enable all currently active pipes while we change cdclk */
|
/* disable/enable all currently active pipes while we change cdclk */
|
||||||
|
@ -4337,10 +4336,9 @@ static void valleyview_modeset_global_resources(struct drm_device *dev)
|
||||||
{
|
{
|
||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
int max_pixclk = intel_mode_max_pixclk(dev_priv);
|
int max_pixclk = intel_mode_max_pixclk(dev_priv);
|
||||||
int cur_cdclk = valleyview_cur_cdclk(dev_priv);
|
|
||||||
int req_cdclk = valleyview_calc_cdclk(dev_priv, max_pixclk);
|
int req_cdclk = valleyview_calc_cdclk(dev_priv, max_pixclk);
|
||||||
|
|
||||||
if (req_cdclk != cur_cdclk)
|
if (req_cdclk != dev_priv->vlv_cdclk_freq)
|
||||||
valleyview_set_cdclk(dev, req_cdclk);
|
valleyview_set_cdclk(dev, req_cdclk);
|
||||||
modeset_update_crtc_power_domains(dev);
|
modeset_update_crtc_power_domains(dev);
|
||||||
}
|
}
|
||||||
|
|
|
@ -665,6 +665,7 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
|
||||||
const char *intel_output_name(int output);
|
const char *intel_output_name(int output);
|
||||||
bool intel_has_pending_fb_unpin(struct drm_device *dev);
|
bool intel_has_pending_fb_unpin(struct drm_device *dev);
|
||||||
int intel_pch_rawclk(struct drm_device *dev);
|
int intel_pch_rawclk(struct drm_device *dev);
|
||||||
|
int valleyview_cur_cdclk(struct drm_i915_private *dev_priv);
|
||||||
void intel_mark_busy(struct drm_device *dev);
|
void intel_mark_busy(struct drm_device *dev);
|
||||||
void intel_mark_fb_busy(struct drm_i915_gem_object *obj,
|
void intel_mark_fb_busy(struct drm_i915_gem_object *obj,
|
||||||
struct intel_ring_buffer *ring);
|
struct intel_ring_buffer *ring);
|
||||||
|
|
|
@ -5078,6 +5078,10 @@ static void valleyview_init_clock_gating(struct drm_device *dev)
|
||||||
}
|
}
|
||||||
DRM_DEBUG_DRIVER("DDR speed: %d MHz", dev_priv->mem_freq);
|
DRM_DEBUG_DRIVER("DDR speed: %d MHz", dev_priv->mem_freq);
|
||||||
|
|
||||||
|
dev_priv->vlv_cdclk_freq = valleyview_cur_cdclk(dev_priv);
|
||||||
|
DRM_DEBUG_DRIVER("Current CD clock rate: %d MHz",
|
||||||
|
dev_priv->vlv_cdclk_freq);
|
||||||
|
|
||||||
I915_WRITE(DSPCLK_GATE_D, VRHUNIT_CLOCK_GATE_DISABLE);
|
I915_WRITE(DSPCLK_GATE_D, VRHUNIT_CLOCK_GATE_DISABLE);
|
||||||
|
|
||||||
/* WaDisableEarlyCull:vlv */
|
/* WaDisableEarlyCull:vlv */
|
||||||
|
|
Loading…
Reference in New Issue