|
@@ -1094,11 +1094,6 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv,
|
|
|
bool cur_state;
|
|
|
struct intel_dpll_hw_state hw_state;
|
|
|
|
|
|
- if (HAS_PCH_LPT(dev_priv->dev)) {
|
|
|
- DRM_DEBUG_DRIVER("LPT detected: skipping PCH PLL test\n");
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
if (WARN (!pll,
|
|
|
"asserting DPLL %s with no DPLL\n", state_string(state)))
|
|
|
return;
|
|
@@ -1514,9 +1509,6 @@ static void intel_reset_dpio(struct drm_device *dev)
|
|
|
{
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
- if (!IS_VALLEYVIEW(dev))
|
|
|
- return;
|
|
|
-
|
|
|
if (IS_CHERRYVIEW(dev)) {
|
|
|
enum dpio_phy phy;
|
|
|
u32 val;
|
|
@@ -1538,26 +1530,6 @@ static void intel_reset_dpio(struct drm_device *dev)
|
|
|
I915_WRITE(DISPLAY_PHY_CONTROL,
|
|
|
PHY_COM_LANE_RESET_DEASSERT(phy, val));
|
|
|
}
|
|
|
-
|
|
|
- } else {
|
|
|
- /*
|
|
|
- * If DPIO has already been reset, e.g. by BIOS, just skip all
|
|
|
- * this.
|
|
|
- */
|
|
|
- if (I915_READ(DPIO_CTL) & DPIO_CMNRST)
|
|
|
- return;
|
|
|
-
|
|
|
- /*
|
|
|
- * From VLV2A0_DP_eDP_HDMI_DPIO_driver_vbios_notes_11.docx:
|
|
|
- * Need to assert and de-assert PHY SB reset by gating the
|
|
|
- * common lane power, then un-gating it.
|
|
|
- * Simply ungating isn't enough to reset the PHY enough to get
|
|
|
- * ports and lanes running.
|
|
|
- */
|
|
|
- __vlv_set_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_BC,
|
|
|
- false);
|
|
|
- __vlv_set_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_BC,
|
|
|
- true);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1837,12 +1809,14 @@ static void intel_enable_shared_dpll(struct intel_crtc *crtc)
|
|
|
}
|
|
|
WARN_ON(pll->on);
|
|
|
|
|
|
+ intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS);
|
|
|
+
|
|
|
DRM_DEBUG_KMS("enabling %s\n", pll->name);
|
|
|
pll->enable(dev_priv, pll);
|
|
|
pll->on = true;
|
|
|
}
|
|
|
|
|
|
-static void intel_disable_shared_dpll(struct intel_crtc *crtc)
|
|
|
+void intel_disable_shared_dpll(struct intel_crtc *crtc)
|
|
|
{
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
@@ -1873,6 +1847,8 @@ static void intel_disable_shared_dpll(struct intel_crtc *crtc)
|
|
|
DRM_DEBUG_KMS("disabling %s\n", pll->name);
|
|
|
pll->disable(dev_priv, pll);
|
|
|
pll->on = false;
|
|
|
+
|
|
|
+ intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
|
|
|
}
|
|
|
|
|
|
static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv,
|
|
@@ -2219,6 +2195,8 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev,
|
|
|
u32 alignment;
|
|
|
int ret;
|
|
|
|
|
|
+ WARN_ON(!mutex_is_locked(&dev->struct_mutex));
|
|
|
+
|
|
|
switch (obj->tiling_mode) {
|
|
|
case I915_TILING_NONE:
|
|
|
if (IS_BROADWATER(dev) || IS_CRESTLINE(dev))
|
|
@@ -2275,6 +2253,8 @@ err_interruptible:
|
|
|
|
|
|
void intel_unpin_fb_obj(struct drm_i915_gem_object *obj)
|
|
|
{
|
|
|
+ WARN_ON(!mutex_is_locked(&obj->base.dev->struct_mutex));
|
|
|
+
|
|
|
i915_gem_object_unpin_fence(obj);
|
|
|
i915_gem_object_unpin_from_display_plane(obj);
|
|
|
}
|
|
@@ -2379,7 +2359,7 @@ static void intel_find_plane_obj(struct intel_crtc *intel_crtc,
|
|
|
struct drm_device *dev = intel_crtc->base.dev;
|
|
|
struct drm_crtc *c;
|
|
|
struct intel_crtc *i;
|
|
|
- struct intel_framebuffer *fb;
|
|
|
+ struct drm_i915_gem_object *obj;
|
|
|
|
|
|
if (!intel_crtc->base.primary->fb)
|
|
|
return;
|
|
@@ -2400,14 +2380,17 @@ static void intel_find_plane_obj(struct intel_crtc *intel_crtc,
|
|
|
if (c == &intel_crtc->base)
|
|
|
continue;
|
|
|
|
|
|
- if (!i->active || !c->primary->fb)
|
|
|
+ if (!i->active)
|
|
|
continue;
|
|
|
|
|
|
- fb = to_intel_framebuffer(c->primary->fb);
|
|
|
- if (i915_gem_obj_ggtt_offset(fb->obj) == plane_config->base) {
|
|
|
+ obj = intel_fb_obj(c->primary->fb);
|
|
|
+ if (obj == NULL)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ if (i915_gem_obj_ggtt_offset(obj) == plane_config->base) {
|
|
|
drm_framebuffer_reference(c->primary->fb);
|
|
|
intel_crtc->base.primary->fb = c->primary->fb;
|
|
|
- fb->obj->frontbuffer_bits |= INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe);
|
|
|
+ obj->frontbuffer_bits |= INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
@@ -2420,16 +2403,12 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
- struct intel_framebuffer *intel_fb;
|
|
|
- struct drm_i915_gem_object *obj;
|
|
|
+ struct drm_i915_gem_object *obj = intel_fb_obj(fb);
|
|
|
int plane = intel_crtc->plane;
|
|
|
unsigned long linear_offset;
|
|
|
u32 dspcntr;
|
|
|
u32 reg;
|
|
|
|
|
|
- intel_fb = to_intel_framebuffer(fb);
|
|
|
- obj = intel_fb->obj;
|
|
|
-
|
|
|
reg = DSPCNTR(plane);
|
|
|
dspcntr = I915_READ(reg);
|
|
|
/* Mask out pixel format bits in case we change it */
|
|
@@ -2510,16 +2489,12 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
- struct intel_framebuffer *intel_fb;
|
|
|
- struct drm_i915_gem_object *obj;
|
|
|
+ struct drm_i915_gem_object *obj = intel_fb_obj(fb);
|
|
|
int plane = intel_crtc->plane;
|
|
|
unsigned long linear_offset;
|
|
|
u32 dspcntr;
|
|
|
u32 reg;
|
|
|
|
|
|
- intel_fb = to_intel_framebuffer(fb);
|
|
|
- obj = intel_fb->obj;
|
|
|
-
|
|
|
reg = DSPCNTR(plane);
|
|
|
dspcntr = I915_READ(reg);
|
|
|
/* Mask out pixel format bits in case we change it */
|
|
@@ -2650,7 +2625,7 @@ void intel_display_handle_reset(struct drm_device *dev)
|
|
|
static int
|
|
|
intel_finish_fb(struct drm_framebuffer *old_fb)
|
|
|
{
|
|
|
- struct drm_i915_gem_object *obj = to_intel_framebuffer(old_fb)->obj;
|
|
|
+ struct drm_i915_gem_object *obj = intel_fb_obj(old_fb);
|
|
|
struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
|
|
|
bool was_interruptible = dev_priv->mm.interruptible;
|
|
|
int ret;
|
|
@@ -2697,8 +2672,9 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
enum pipe pipe = intel_crtc->pipe;
|
|
|
- struct drm_framebuffer *old_fb;
|
|
|
- struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)->obj;
|
|
|
+ struct drm_framebuffer *old_fb = crtc->primary->fb;
|
|
|
+ struct drm_i915_gem_object *obj = intel_fb_obj(fb);
|
|
|
+ struct drm_i915_gem_object *old_obj = intel_fb_obj(old_fb);
|
|
|
int ret;
|
|
|
|
|
|
if (intel_crtc_has_pending_flip(crtc)) {
|
|
@@ -2719,12 +2695,10 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
- old_fb = crtc->primary->fb;
|
|
|
-
|
|
|
mutex_lock(&dev->struct_mutex);
|
|
|
ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
|
|
|
if (ret == 0)
|
|
|
- i915_gem_track_fb(to_intel_framebuffer(old_fb)->obj, obj,
|
|
|
+ i915_gem_track_fb(old_obj, obj,
|
|
|
INTEL_FRONTBUFFER_PRIMARY(pipe));
|
|
|
mutex_unlock(&dev->struct_mutex);
|
|
|
if (ret != 0) {
|
|
@@ -2776,7 +2750,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
|
|
|
if (intel_crtc->active && old_fb != fb)
|
|
|
intel_wait_for_vblank(dev, intel_crtc->pipe);
|
|
|
mutex_lock(&dev->struct_mutex);
|
|
|
- intel_unpin_fb_obj(to_intel_framebuffer(old_fb)->obj);
|
|
|
+ intel_unpin_fb_obj(old_obj);
|
|
|
mutex_unlock(&dev->struct_mutex);
|
|
|
}
|
|
|
|
|
@@ -3642,7 +3616,7 @@ static void lpt_pch_enable(struct drm_crtc *crtc)
|
|
|
lpt_enable_pch_transcoder(dev_priv, cpu_transcoder);
|
|
|
}
|
|
|
|
|
|
-static void intel_put_shared_dpll(struct intel_crtc *crtc)
|
|
|
+void intel_put_shared_dpll(struct intel_crtc *crtc)
|
|
|
{
|
|
|
struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
|
|
|
|
|
@@ -3662,7 +3636,7 @@ static void intel_put_shared_dpll(struct intel_crtc *crtc)
|
|
|
crtc->config.shared_dpll = DPLL_ID_PRIVATE;
|
|
|
}
|
|
|
|
|
|
-static struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc)
|
|
|
+struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc)
|
|
|
{
|
|
|
struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
|
|
|
struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
|
|
@@ -3915,30 +3889,6 @@ static void intel_crtc_dpms_overlay(struct intel_crtc *intel_crtc, bool enable)
|
|
|
*/
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * i9xx_fixup_plane - ugly workaround for G45 to fire up the hardware
|
|
|
- * cursor plane briefly if not already running after enabling the display
|
|
|
- * plane.
|
|
|
- * This workaround avoids occasional blank screens when self refresh is
|
|
|
- * enabled.
|
|
|
- */
|
|
|
-static void
|
|
|
-g4x_fixup_plane(struct drm_i915_private *dev_priv, enum pipe pipe)
|
|
|
-{
|
|
|
- u32 cntl = I915_READ(CURCNTR(pipe));
|
|
|
-
|
|
|
- if ((cntl & CURSOR_MODE) == 0) {
|
|
|
- u32 fw_bcl_self = I915_READ(FW_BLC_SELF);
|
|
|
-
|
|
|
- I915_WRITE(FW_BLC_SELF, fw_bcl_self & ~FW_BLC_SELF_EN);
|
|
|
- I915_WRITE(CURCNTR(pipe), CURSOR_MODE_64_ARGB_AX);
|
|
|
- intel_wait_for_vblank(dev_priv->dev, pipe);
|
|
|
- I915_WRITE(CURCNTR(pipe), cntl);
|
|
|
- I915_WRITE(CURBASE(pipe), I915_READ(CURBASE(pipe)));
|
|
|
- I915_WRITE(FW_BLC_SELF, fw_bcl_self);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
static void intel_crtc_enable_planes(struct drm_crtc *crtc)
|
|
|
{
|
|
|
struct drm_device *dev = crtc->dev;
|
|
@@ -3951,9 +3901,6 @@ static void intel_crtc_enable_planes(struct drm_crtc *crtc)
|
|
|
|
|
|
intel_enable_primary_hw_plane(dev_priv, plane, pipe);
|
|
|
intel_enable_planes(crtc);
|
|
|
- /* The fixup needs to happen before cursor is enabled */
|
|
|
- if (IS_G4X(dev))
|
|
|
- g4x_fixup_plane(dev_priv, pipe);
|
|
|
intel_crtc_update_cursor(crtc, true);
|
|
|
intel_crtc_dpms_overlay(intel_crtc, true);
|
|
|
|
|
@@ -4128,6 +4075,9 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
|
|
|
if (intel_crtc->active)
|
|
|
return;
|
|
|
|
|
|
+ if (intel_crtc_to_shared_dpll(intel_crtc))
|
|
|
+ intel_enable_shared_dpll(intel_crtc);
|
|
|
+
|
|
|
if (intel_crtc->config.has_dp_encoder)
|
|
|
intel_dp_set_m_n(intel_crtc);
|
|
|
|
|
@@ -4152,16 +4102,15 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
|
|
|
intel_crtc->active = true;
|
|
|
|
|
|
intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
|
|
|
- if (intel_crtc->config.has_pch_encoder)
|
|
|
- intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, true);
|
|
|
-
|
|
|
- if (intel_crtc->config.has_pch_encoder)
|
|
|
- dev_priv->display.fdi_link_train(crtc);
|
|
|
-
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
if (encoder->pre_enable)
|
|
|
encoder->pre_enable(encoder);
|
|
|
|
|
|
+ if (intel_crtc->config.has_pch_encoder) {
|
|
|
+ intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, true);
|
|
|
+ dev_priv->display.fdi_link_train(crtc);
|
|
|
+ }
|
|
|
+
|
|
|
intel_ddi_enable_pipe_clock(intel_crtc);
|
|
|
|
|
|
ironlake_pfit_enable(intel_crtc);
|
|
@@ -4299,22 +4248,25 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
|
|
|
|
|
|
intel_ddi_disable_pipe_clock(intel_crtc);
|
|
|
|
|
|
- for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
- if (encoder->post_disable)
|
|
|
- encoder->post_disable(encoder);
|
|
|
-
|
|
|
if (intel_crtc->config.has_pch_encoder) {
|
|
|
lpt_disable_pch_transcoder(dev_priv);
|
|
|
intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, true);
|
|
|
intel_ddi_fdi_disable(crtc);
|
|
|
}
|
|
|
|
|
|
+ for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
+ if (encoder->post_disable)
|
|
|
+ encoder->post_disable(encoder);
|
|
|
+
|
|
|
intel_crtc->active = false;
|
|
|
intel_update_watermarks(crtc);
|
|
|
|
|
|
mutex_lock(&dev->struct_mutex);
|
|
|
intel_update_fbc(dev);
|
|
|
mutex_unlock(&dev->struct_mutex);
|
|
|
+
|
|
|
+ if (intel_crtc_to_shared_dpll(intel_crtc))
|
|
|
+ intel_disable_shared_dpll(intel_crtc);
|
|
|
}
|
|
|
|
|
|
static void ironlake_crtc_off(struct drm_crtc *crtc)
|
|
@@ -4323,10 +4275,6 @@ static void ironlake_crtc_off(struct drm_crtc *crtc)
|
|
|
intel_put_shared_dpll(intel_crtc);
|
|
|
}
|
|
|
|
|
|
-static void haswell_crtc_off(struct drm_crtc *crtc)
|
|
|
-{
|
|
|
- intel_ddi_put_crtc_pll(crtc);
|
|
|
-}
|
|
|
|
|
|
static void i9xx_pfit_enable(struct intel_crtc *crtc)
|
|
|
{
|
|
@@ -4398,7 +4346,6 @@ static unsigned long get_crtc_power_domains(struct drm_crtc *crtc)
|
|
|
struct intel_encoder *intel_encoder;
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
enum pipe pipe = intel_crtc->pipe;
|
|
|
- bool pfit_enabled = intel_crtc->config.pch_pfit.enabled;
|
|
|
unsigned long mask;
|
|
|
enum transcoder transcoder;
|
|
|
|
|
@@ -4406,7 +4353,8 @@ static unsigned long get_crtc_power_domains(struct drm_crtc *crtc)
|
|
|
|
|
|
mask = BIT(POWER_DOMAIN_PIPE(pipe));
|
|
|
mask |= BIT(POWER_DOMAIN_TRANSCODER(transcoder));
|
|
|
- if (pfit_enabled)
|
|
|
+ if (intel_crtc->config.pch_pfit.enabled ||
|
|
|
+ intel_crtc->config.pch_pfit.force_thru)
|
|
|
mask |= BIT(POWER_DOMAIN_PIPE_PANEL_FITTER(pipe));
|
|
|
|
|
|
for_each_encoder_on_crtc(dev, crtc, intel_encoder)
|
|
@@ -4463,7 +4411,8 @@ static void modeset_update_crtc_power_domains(struct drm_device *dev)
|
|
|
intel_display_set_init_power(dev_priv, false);
|
|
|
}
|
|
|
|
|
|
-int valleyview_get_vco(struct drm_i915_private *dev_priv)
|
|
|
+/* returns HPLL frequency in kHz */
|
|
|
+static int valleyview_get_vco(struct drm_i915_private *dev_priv)
|
|
|
{
|
|
|
int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 };
|
|
|
|
|
@@ -4473,7 +4422,23 @@ int valleyview_get_vco(struct drm_i915_private *dev_priv)
|
|
|
CCK_FUSE_HPLL_FREQ_MASK;
|
|
|
mutex_unlock(&dev_priv->dpio_lock);
|
|
|
|
|
|
- return vco_freq[hpll_freq];
|
|
|
+ return vco_freq[hpll_freq] * 1000;
|
|
|
+}
|
|
|
+
|
|
|
+static void vlv_update_cdclk(struct drm_device *dev)
|
|
|
+{
|
|
|
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
+
|
|
|
+ dev_priv->vlv_cdclk_freq = dev_priv->display.get_display_clock_speed(dev);
|
|
|
+ DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz",
|
|
|
+ dev_priv->vlv_cdclk_freq);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Program the gmbus_freq based on the cdclk frequency.
|
|
|
+ * BSpec erroneously claims we should aim for 4MHz, but
|
|
|
+ * in fact 1MHz is the correct frequency.
|
|
|
+ */
|
|
|
+ I915_WRITE(GMBUSFREQ_VLV, dev_priv->vlv_cdclk_freq);
|
|
|
}
|
|
|
|
|
|
/* Adjust CDclk dividers to allow high res or save power if possible */
|
|
@@ -4482,12 +4447,11 @@ static void valleyview_set_cdclk(struct drm_device *dev, int cdclk)
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
u32 val, cmd;
|
|
|
|
|
|
- WARN_ON(valleyview_cur_cdclk(dev_priv) != dev_priv->vlv_cdclk_freq);
|
|
|
- dev_priv->vlv_cdclk_freq = cdclk;
|
|
|
+ WARN_ON(dev_priv->display.get_display_clock_speed(dev) != dev_priv->vlv_cdclk_freq);
|
|
|
|
|
|
- if (cdclk >= 320) /* jump to highest voltage for 400MHz too */
|
|
|
+ if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */
|
|
|
cmd = 2;
|
|
|
- else if (cdclk == 266)
|
|
|
+ else if (cdclk == 266667)
|
|
|
cmd = 1;
|
|
|
else
|
|
|
cmd = 0;
|
|
@@ -4504,18 +4468,23 @@ static void valleyview_set_cdclk(struct drm_device *dev, int cdclk)
|
|
|
}
|
|
|
mutex_unlock(&dev_priv->rps.hw_lock);
|
|
|
|
|
|
- if (cdclk == 400) {
|
|
|
+ if (cdclk == 400000) {
|
|
|
u32 divider, vco;
|
|
|
|
|
|
vco = valleyview_get_vco(dev_priv);
|
|
|
- divider = ((vco << 1) / cdclk) - 1;
|
|
|
+ divider = DIV_ROUND_CLOSEST(vco << 1, cdclk) - 1;
|
|
|
|
|
|
mutex_lock(&dev_priv->dpio_lock);
|
|
|
/* adjust cdclk divider */
|
|
|
val = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL);
|
|
|
- val &= ~0xf;
|
|
|
+ val &= ~DISPLAY_FREQUENCY_VALUES;
|
|
|
val |= divider;
|
|
|
vlv_cck_write(dev_priv, CCK_DISPLAY_CLOCK_CONTROL, val);
|
|
|
+
|
|
|
+ if (wait_for((vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL) &
|
|
|
+ DISPLAY_FREQUENCY_STATUS) == (divider << DISPLAY_FREQUENCY_STATUS_SHIFT),
|
|
|
+ 50))
|
|
|
+ DRM_ERROR("timed out waiting for CDclk change\n");
|
|
|
mutex_unlock(&dev_priv->dpio_lock);
|
|
|
}
|
|
|
|
|
@@ -4528,54 +4497,43 @@ static void valleyview_set_cdclk(struct drm_device *dev, int cdclk)
|
|
|
* For high bandwidth configs, we set a higher latency in the bunit
|
|
|
* so that the core display fetch happens in time to avoid underruns.
|
|
|
*/
|
|
|
- if (cdclk == 400)
|
|
|
+ if (cdclk == 400000)
|
|
|
val |= 4500 / 250; /* 4.5 usec */
|
|
|
else
|
|
|
val |= 3000 / 250; /* 3.0 usec */
|
|
|
vlv_bunit_write(dev_priv, BUNIT_REG_BISOC, val);
|
|
|
mutex_unlock(&dev_priv->dpio_lock);
|
|
|
|
|
|
- /* Since we changed the CDclk, we need to update the GMBUSFREQ too */
|
|
|
- intel_i2c_reset(dev);
|
|
|
-}
|
|
|
-
|
|
|
-int valleyview_cur_cdclk(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- int cur_cdclk, vco;
|
|
|
- int divider;
|
|
|
-
|
|
|
- vco = valleyview_get_vco(dev_priv);
|
|
|
-
|
|
|
- mutex_lock(&dev_priv->dpio_lock);
|
|
|
- divider = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL);
|
|
|
- mutex_unlock(&dev_priv->dpio_lock);
|
|
|
-
|
|
|
- divider &= 0xf;
|
|
|
-
|
|
|
- cur_cdclk = (vco << 1) / (divider + 1);
|
|
|
-
|
|
|
- return cur_cdclk;
|
|
|
+ vlv_update_cdclk(dev);
|
|
|
}
|
|
|
|
|
|
static int valleyview_calc_cdclk(struct drm_i915_private *dev_priv,
|
|
|
int max_pixclk)
|
|
|
{
|
|
|
+ int vco = valleyview_get_vco(dev_priv);
|
|
|
+ int freq_320 = (vco << 1) % 320000 != 0 ? 333333 : 320000;
|
|
|
+
|
|
|
/*
|
|
|
* Really only a few cases to deal with, as only 4 CDclks are supported:
|
|
|
* 200MHz
|
|
|
* 267MHz
|
|
|
- * 320MHz
|
|
|
+ * 320/333MHz (depends on HPLL freq)
|
|
|
* 400MHz
|
|
|
* So we check to see whether we're above 90% of the lower bin and
|
|
|
* adjust if needed.
|
|
|
+ *
|
|
|
+ * We seem to get an unstable or solid color picture at 200MHz.
|
|
|
+ * Not sure what's wrong. For now use 200MHz only when all pipes
|
|
|
+ * are off.
|
|
|
*/
|
|
|
- if (max_pixclk > 288000) {
|
|
|
- return 400;
|
|
|
- } else if (max_pixclk > 240000) {
|
|
|
- return 320;
|
|
|
- } else
|
|
|
- return 266;
|
|
|
- /* Looks like the 200MHz CDclk freq doesn't work on some configs */
|
|
|
+ if (max_pixclk > freq_320*9/10)
|
|
|
+ return 400000;
|
|
|
+ else if (max_pixclk > 266667*9/10)
|
|
|
+ return freq_320;
|
|
|
+ else if (max_pixclk > 0)
|
|
|
+ return 266667;
|
|
|
+ else
|
|
|
+ return 200000;
|
|
|
}
|
|
|
|
|
|
/* compute the max pixel clock for new configuration */
|
|
@@ -4829,6 +4787,16 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
|
|
|
if (IS_GEN2(dev))
|
|
|
intel_set_cpu_fifo_underrun_reporting(dev, pipe, false);
|
|
|
|
|
|
+ /*
|
|
|
+ * Vblank time updates from the shadow to live plane control register
|
|
|
+ * are blocked if the memory self-refresh mode is active at that
|
|
|
+ * moment. So to make sure the plane gets truly disabled, disable
|
|
|
+ * first the self-refresh mode. The self-refresh enable bit in turn
|
|
|
+ * will be checked/applied by the HW only at the next frame start
|
|
|
+ * event which is after the vblank start event, so we need to have a
|
|
|
+ * wait-for-vblank between disabling the plane and the pipe.
|
|
|
+ */
|
|
|
+ intel_set_memory_cxsr(dev_priv, false);
|
|
|
intel_crtc_disable_planes(crtc);
|
|
|
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
@@ -4837,9 +4805,10 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
|
|
|
/*
|
|
|
* On gen2 planes are double buffered but the pipe isn't, so we must
|
|
|
* wait for planes to fully turn off before disabling the pipe.
|
|
|
+ * We also need to wait on all gmch platforms because of the
|
|
|
+ * self-refresh mode constraint explained above.
|
|
|
*/
|
|
|
- if (IS_GEN2(dev))
|
|
|
- intel_wait_for_vblank(dev, pipe);
|
|
|
+ intel_wait_for_vblank(dev, pipe);
|
|
|
|
|
|
intel_disable_pipe(dev_priv, pipe);
|
|
|
|
|
@@ -4956,7 +4925,7 @@ static void intel_crtc_disable(struct drm_crtc *crtc)
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
struct drm_connector *connector;
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
- struct drm_i915_gem_object *old_obj;
|
|
|
+ struct drm_i915_gem_object *old_obj = intel_fb_obj(crtc->primary->fb);
|
|
|
enum pipe pipe = to_intel_crtc(crtc)->pipe;
|
|
|
|
|
|
/* crtc should still be enabled when we disable it. */
|
|
@@ -4971,7 +4940,6 @@ static void intel_crtc_disable(struct drm_crtc *crtc)
|
|
|
assert_pipe_disabled(dev->dev_private, pipe);
|
|
|
|
|
|
if (crtc->primary->fb) {
|
|
|
- old_obj = to_intel_framebuffer(crtc->primary->fb)->obj;
|
|
|
mutex_lock(&dev->struct_mutex);
|
|
|
intel_unpin_fb_obj(old_obj);
|
|
|
i915_gem_track_fb(old_obj, NULL,
|
|
@@ -5253,9 +5221,11 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
|
|
|
if (HAS_IPS(dev))
|
|
|
hsw_compute_ips_config(crtc, pipe_config);
|
|
|
|
|
|
- /* XXX: PCH clock sharing is done in ->mode_set, so make sure the old
|
|
|
- * clock survives for now. */
|
|
|
- if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
|
|
|
+ /*
|
|
|
+ * XXX: PCH/WRPLL clock sharing is done in ->mode_set, so make sure the
|
|
|
+ * old clock survives for now.
|
|
|
+ */
|
|
|
+ if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev) || HAS_DDI(dev))
|
|
|
pipe_config->shared_dpll = crtc->config.shared_dpll;
|
|
|
|
|
|
if (pipe_config->has_pch_encoder)
|
|
@@ -5266,7 +5236,22 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
|
|
|
|
|
|
static int valleyview_get_display_clock_speed(struct drm_device *dev)
|
|
|
{
|
|
|
- return 400000; /* FIXME */
|
|
|
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
+ int vco = valleyview_get_vco(dev_priv);
|
|
|
+ u32 val;
|
|
|
+ int divider;
|
|
|
+
|
|
|
+ mutex_lock(&dev_priv->dpio_lock);
|
|
|
+ val = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL);
|
|
|
+ mutex_unlock(&dev_priv->dpio_lock);
|
|
|
+
|
|
|
+ divider = val & DISPLAY_FREQUENCY_VALUES;
|
|
|
+
|
|
|
+ WARN((val & DISPLAY_FREQUENCY_STATUS) !=
|
|
|
+ (divider << DISPLAY_FREQUENCY_STATUS_SHIFT),
|
|
|
+ "cdclk change in progress\n");
|
|
|
+
|
|
|
+ return DIV_ROUND_CLOSEST(vco << 1, divider + 1);
|
|
|
}
|
|
|
|
|
|
static int i945_get_display_clock_speed(struct drm_device *dev)
|
|
@@ -6217,8 +6202,8 @@ static void i9xx_get_plane_config(struct intel_crtc *crtc,
|
|
|
aligned_height = intel_align_height(dev, crtc->base.primary->fb->height,
|
|
|
plane_config->tiled);
|
|
|
|
|
|
- plane_config->size = ALIGN(crtc->base.primary->fb->pitches[0] *
|
|
|
- aligned_height, PAGE_SIZE);
|
|
|
+ plane_config->size = PAGE_ALIGN(crtc->base.primary->fb->pitches[0] *
|
|
|
+ aligned_height);
|
|
|
|
|
|
DRM_DEBUG_KMS("pipe/plane %d/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
|
|
|
pipe, plane, crtc->base.primary->fb->width,
|
|
@@ -7237,8 +7222,8 @@ static void ironlake_get_plane_config(struct intel_crtc *crtc,
|
|
|
aligned_height = intel_align_height(dev, crtc->base.primary->fb->height,
|
|
|
plane_config->tiled);
|
|
|
|
|
|
- plane_config->size = ALIGN(crtc->base.primary->fb->pitches[0] *
|
|
|
- aligned_height, PAGE_SIZE);
|
|
|
+ plane_config->size = PAGE_ALIGN(crtc->base.primary->fb->pitches[0] *
|
|
|
+ aligned_height);
|
|
|
|
|
|
DRM_DEBUG_KMS("pipe/plane %d/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
|
|
|
pipe, plane, crtc->base.primary->fb->width,
|
|
@@ -7255,6 +7240,10 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
uint32_t tmp;
|
|
|
|
|
|
+ if (!intel_display_power_enabled(dev_priv,
|
|
|
+ POWER_DOMAIN_PIPE(crtc->pipe)))
|
|
|
+ return false;
|
|
|
+
|
|
|
pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
|
|
|
pipe_config->shared_dpll = DPLL_ID_PRIVATE;
|
|
|
|
|
@@ -7329,7 +7318,6 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
|
|
|
static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
|
|
|
{
|
|
|
struct drm_device *dev = dev_priv->dev;
|
|
|
- struct intel_ddi_plls *plls = &dev_priv->ddi_plls;
|
|
|
struct intel_crtc *crtc;
|
|
|
|
|
|
for_each_intel_crtc(dev, crtc)
|
|
@@ -7337,9 +7325,9 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
|
|
|
pipe_name(crtc->pipe));
|
|
|
|
|
|
WARN(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on\n");
|
|
|
- WARN(plls->spll_refcount, "SPLL enabled\n");
|
|
|
- WARN(plls->wrpll1_refcount, "WRPLL1 enabled\n");
|
|
|
- WARN(plls->wrpll2_refcount, "WRPLL2 enabled\n");
|
|
|
+ WARN(I915_READ(SPLL_CTL) & SPLL_PLL_ENABLE, "SPLL enabled\n");
|
|
|
+ WARN(I915_READ(WRPLL_CTL1) & WRPLL_PLL_ENABLE, "WRPLL1 enabled\n");
|
|
|
+ WARN(I915_READ(WRPLL_CTL2) & WRPLL_PLL_ENABLE, "WRPLL2 enabled\n");
|
|
|
WARN(I915_READ(PCH_PP_STATUS) & PP_ON, "Panel power on\n");
|
|
|
WARN(I915_READ(BLC_PWM_CPU_CTL2) & BLM_PWM_ENABLE,
|
|
|
"CPU PWM1 enabled\n");
|
|
@@ -7360,6 +7348,16 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
|
|
|
WARN(!dev_priv->pm.irqs_disabled, "IRQs enabled\n");
|
|
|
}
|
|
|
|
|
|
+static uint32_t hsw_read_dcomp(struct drm_i915_private *dev_priv)
|
|
|
+{
|
|
|
+ struct drm_device *dev = dev_priv->dev;
|
|
|
+
|
|
|
+ if (IS_HASWELL(dev))
|
|
|
+ return I915_READ(D_COMP_HSW);
|
|
|
+ else
|
|
|
+ return I915_READ(D_COMP_BDW);
|
|
|
+}
|
|
|
+
|
|
|
static void hsw_write_dcomp(struct drm_i915_private *dev_priv, uint32_t val)
|
|
|
{
|
|
|
struct drm_device *dev = dev_priv->dev;
|
|
@@ -7368,12 +7366,12 @@ static void hsw_write_dcomp(struct drm_i915_private *dev_priv, uint32_t val)
|
|
|
mutex_lock(&dev_priv->rps.hw_lock);
|
|
|
if (sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_D_COMP,
|
|
|
val))
|
|
|
- DRM_ERROR("Failed to disable D_COMP\n");
|
|
|
+ DRM_ERROR("Failed to write to D_COMP\n");
|
|
|
mutex_unlock(&dev_priv->rps.hw_lock);
|
|
|
} else {
|
|
|
- I915_WRITE(D_COMP, val);
|
|
|
+ I915_WRITE(D_COMP_BDW, val);
|
|
|
+ POSTING_READ(D_COMP_BDW);
|
|
|
}
|
|
|
- POSTING_READ(D_COMP);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -7411,12 +7409,13 @@ static void hsw_disable_lcpll(struct drm_i915_private *dev_priv,
|
|
|
if (wait_for((I915_READ(LCPLL_CTL) & LCPLL_PLL_LOCK) == 0, 1))
|
|
|
DRM_ERROR("LCPLL still locked\n");
|
|
|
|
|
|
- val = I915_READ(D_COMP);
|
|
|
+ val = hsw_read_dcomp(dev_priv);
|
|
|
val |= D_COMP_COMP_DISABLE;
|
|
|
hsw_write_dcomp(dev_priv, val);
|
|
|
ndelay(100);
|
|
|
|
|
|
- if (wait_for((I915_READ(D_COMP) & D_COMP_RCOMP_IN_PROGRESS) == 0, 1))
|
|
|
+ if (wait_for((hsw_read_dcomp(dev_priv) & D_COMP_RCOMP_IN_PROGRESS) == 0,
|
|
|
+ 1))
|
|
|
DRM_ERROR("D_COMP RCOMP still in progress\n");
|
|
|
|
|
|
if (allow_power_down) {
|
|
@@ -7465,7 +7464,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
|
|
|
POSTING_READ(LCPLL_CTL);
|
|
|
}
|
|
|
|
|
|
- val = I915_READ(D_COMP);
|
|
|
+ val = hsw_read_dcomp(dev_priv);
|
|
|
val |= D_COMP_COMP_FORCE;
|
|
|
val &= ~D_COMP_COMP_DISABLE;
|
|
|
hsw_write_dcomp(dev_priv, val);
|
|
@@ -7571,13 +7570,59 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
|
|
|
|
|
|
if (!intel_ddi_pll_select(intel_crtc))
|
|
|
return -EINVAL;
|
|
|
- intel_ddi_pll_enable(intel_crtc);
|
|
|
|
|
|
intel_crtc->lowfreq_avail = false;
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static void haswell_get_ddi_port_state(struct intel_crtc *crtc,
|
|
|
+ struct intel_crtc_config *pipe_config)
|
|
|
+{
|
|
|
+ struct drm_device *dev = crtc->base.dev;
|
|
|
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
+ struct intel_shared_dpll *pll;
|
|
|
+ enum port port;
|
|
|
+ uint32_t tmp;
|
|
|
+
|
|
|
+ tmp = I915_READ(TRANS_DDI_FUNC_CTL(pipe_config->cpu_transcoder));
|
|
|
+
|
|
|
+ port = (tmp & TRANS_DDI_PORT_MASK) >> TRANS_DDI_PORT_SHIFT;
|
|
|
+
|
|
|
+ pipe_config->ddi_pll_sel = I915_READ(PORT_CLK_SEL(port));
|
|
|
+
|
|
|
+ switch (pipe_config->ddi_pll_sel) {
|
|
|
+ case PORT_CLK_SEL_WRPLL1:
|
|
|
+ pipe_config->shared_dpll = DPLL_ID_WRPLL1;
|
|
|
+ break;
|
|
|
+ case PORT_CLK_SEL_WRPLL2:
|
|
|
+ pipe_config->shared_dpll = DPLL_ID_WRPLL2;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (pipe_config->shared_dpll >= 0) {
|
|
|
+ pll = &dev_priv->shared_dplls[pipe_config->shared_dpll];
|
|
|
+
|
|
|
+ WARN_ON(!pll->get_hw_state(dev_priv, pll,
|
|
|
+ &pipe_config->dpll_hw_state));
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Haswell has only FDI/PCH transcoder A. It is which is connected to
|
|
|
+ * DDI E. So just check whether this pipe is wired to DDI E and whether
|
|
|
+ * the PCH transcoder is on.
|
|
|
+ */
|
|
|
+ if ((port == PORT_E) && I915_READ(LPT_TRANSCONF) & TRANS_ENABLE) {
|
|
|
+ pipe_config->has_pch_encoder = true;
|
|
|
+
|
|
|
+ tmp = I915_READ(FDI_RX_CTL(PIPE_A));
|
|
|
+ pipe_config->fdi_lanes = ((FDI_DP_PORT_WIDTH_MASK & tmp) >>
|
|
|
+ FDI_DP_PORT_WIDTH_SHIFT) + 1;
|
|
|
+
|
|
|
+ ironlake_get_fdi_m_n_config(crtc, pipe_config);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static bool haswell_get_pipe_config(struct intel_crtc *crtc,
|
|
|
struct intel_crtc_config *pipe_config)
|
|
|
{
|
|
@@ -7623,22 +7668,7 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
|
|
|
if (!(tmp & PIPECONF_ENABLE))
|
|
|
return false;
|
|
|
|
|
|
- /*
|
|
|
- * Haswell has only FDI/PCH transcoder A. It is which is connected to
|
|
|
- * DDI E. So just check whether this pipe is wired to DDI E and whether
|
|
|
- * the PCH transcoder is on.
|
|
|
- */
|
|
|
- tmp = I915_READ(TRANS_DDI_FUNC_CTL(pipe_config->cpu_transcoder));
|
|
|
- if ((tmp & TRANS_DDI_PORT_MASK) == TRANS_DDI_SELECT_PORT(PORT_E) &&
|
|
|
- I915_READ(LPT_TRANSCONF) & TRANS_ENABLE) {
|
|
|
- pipe_config->has_pch_encoder = true;
|
|
|
-
|
|
|
- tmp = I915_READ(FDI_RX_CTL(PIPE_A));
|
|
|
- pipe_config->fdi_lanes = ((FDI_DP_PORT_WIDTH_MASK & tmp) >>
|
|
|
- FDI_DP_PORT_WIDTH_SHIFT) + 1;
|
|
|
-
|
|
|
- ironlake_get_fdi_m_n_config(crtc, pipe_config);
|
|
|
- }
|
|
|
+ haswell_get_ddi_port_state(crtc, pipe_config);
|
|
|
|
|
|
intel_get_pipe_timings(crtc, pipe_config);
|
|
|
|
|
@@ -8326,7 +8356,7 @@ static u32
|
|
|
intel_framebuffer_size_for_mode(struct drm_display_mode *mode, int bpp)
|
|
|
{
|
|
|
u32 pitch = intel_framebuffer_pitch_for_width(mode->hdisplay, bpp);
|
|
|
- return ALIGN(pitch * mode->vdisplay, PAGE_SIZE);
|
|
|
+ return PAGE_ALIGN(pitch * mode->vdisplay);
|
|
|
}
|
|
|
|
|
|
static struct drm_framebuffer *
|
|
@@ -9447,6 +9477,9 @@ static bool use_mmio_flip(struct intel_engine_cs *ring,
|
|
|
* So using MMIO flips there would disrupt this mechanism.
|
|
|
*/
|
|
|
|
|
|
+ if (ring == NULL)
|
|
|
+ return true;
|
|
|
+
|
|
|
if (INTEL_INFO(ring->dev)->gen < 5)
|
|
|
return false;
|
|
|
|
|
@@ -9595,7 +9628,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
struct drm_framebuffer *old_fb = crtc->primary->fb;
|
|
|
- struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)->obj;
|
|
|
+ struct drm_i915_gem_object *obj = intel_fb_obj(fb);
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
enum pipe pipe = intel_crtc->pipe;
|
|
|
struct intel_unpin_work *work;
|
|
@@ -9603,6 +9636,14 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
|
|
|
unsigned long flags;
|
|
|
int ret;
|
|
|
|
|
|
+ /*
|
|
|
+ * drm_mode_page_flip_ioctl() should already catch this, but double
|
|
|
+ * check to be safe. In the future we may enable pageflipping from
|
|
|
+ * a disabled primary plane.
|
|
|
+ */
|
|
|
+ if (WARN_ON(intel_fb_obj(old_fb) == NULL))
|
|
|
+ return -EBUSY;
|
|
|
+
|
|
|
/* Can't change pixel format via MI display flips. */
|
|
|
if (fb->pixel_format != crtc->primary->fb->pixel_format)
|
|
|
return -EINVAL;
|
|
@@ -9625,7 +9666,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
|
|
|
|
|
|
work->event = event;
|
|
|
work->crtc = crtc;
|
|
|
- work->old_fb_obj = to_intel_framebuffer(old_fb)->obj;
|
|
|
+ work->old_fb_obj = intel_fb_obj(old_fb);
|
|
|
INIT_WORK(&work->work, intel_unpin_work_fn);
|
|
|
|
|
|
ret = drm_crtc_vblank_get(crtc);
|
|
@@ -9670,6 +9711,11 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
|
|
|
|
|
|
if (IS_VALLEYVIEW(dev)) {
|
|
|
ring = &dev_priv->ring[BCS];
|
|
|
+ if (obj->tiling_mode != work->old_fb_obj->tiling_mode)
|
|
|
+ /* vlv: DISPLAY_FLIP fails to change tiling */
|
|
|
+ ring = NULL;
|
|
|
+ } else if (IS_IVYBRIDGE(dev)) {
|
|
|
+ ring = &dev_priv->ring[BCS];
|
|
|
} else if (INTEL_INFO(dev)->gen >= 7) {
|
|
|
ring = obj->ring;
|
|
|
if (ring == NULL || ring->id != RCS)
|
|
@@ -10401,11 +10447,14 @@ intel_pipe_config_compare(struct drm_device *dev,
|
|
|
|
|
|
PIPE_CONF_CHECK_I(double_wide);
|
|
|
|
|
|
+ PIPE_CONF_CHECK_X(ddi_pll_sel);
|
|
|
+
|
|
|
PIPE_CONF_CHECK_I(shared_dpll);
|
|
|
PIPE_CONF_CHECK_X(dpll_hw_state.dpll);
|
|
|
PIPE_CONF_CHECK_X(dpll_hw_state.dpll_md);
|
|
|
PIPE_CONF_CHECK_X(dpll_hw_state.fp0);
|
|
|
PIPE_CONF_CHECK_X(dpll_hw_state.fp1);
|
|
|
+ PIPE_CONF_CHECK_X(dpll_hw_state.wrpll);
|
|
|
|
|
|
if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5)
|
|
|
PIPE_CONF_CHECK_I(pipe_bpp);
|
|
@@ -10762,10 +10811,9 @@ static int __intel_set_mode(struct drm_crtc *crtc,
|
|
|
* on the DPLL.
|
|
|
*/
|
|
|
for_each_intel_crtc_masked(dev, modeset_pipes, intel_crtc) {
|
|
|
- struct drm_framebuffer *old_fb;
|
|
|
- struct drm_i915_gem_object *old_obj = NULL;
|
|
|
- struct drm_i915_gem_object *obj =
|
|
|
- to_intel_framebuffer(fb)->obj;
|
|
|
+ struct drm_framebuffer *old_fb = crtc->primary->fb;
|
|
|
+ struct drm_i915_gem_object *old_obj = intel_fb_obj(old_fb);
|
|
|
+ struct drm_i915_gem_object *obj = intel_fb_obj(fb);
|
|
|
|
|
|
mutex_lock(&dev->struct_mutex);
|
|
|
ret = intel_pin_and_fence_fb_obj(dev,
|
|
@@ -10776,11 +10824,8 @@ static int __intel_set_mode(struct drm_crtc *crtc,
|
|
|
mutex_unlock(&dev->struct_mutex);
|
|
|
goto done;
|
|
|
}
|
|
|
- old_fb = crtc->primary->fb;
|
|
|
- if (old_fb) {
|
|
|
- old_obj = to_intel_framebuffer(old_fb)->obj;
|
|
|
+ if (old_fb)
|
|
|
intel_unpin_fb_obj(old_obj);
|
|
|
- }
|
|
|
i915_gem_track_fb(old_obj, obj,
|
|
|
INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe));
|
|
|
mutex_unlock(&dev->struct_mutex);
|
|
@@ -11266,18 +11311,15 @@ static const struct drm_crtc_funcs intel_crtc_funcs = {
|
|
|
.page_flip = intel_crtc_page_flip,
|
|
|
};
|
|
|
|
|
|
-static void intel_cpu_pll_init(struct drm_device *dev)
|
|
|
-{
|
|
|
- if (HAS_DDI(dev))
|
|
|
- intel_ddi_pll_init(dev);
|
|
|
-}
|
|
|
-
|
|
|
static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
|
|
|
struct intel_shared_dpll *pll,
|
|
|
struct intel_dpll_hw_state *hw_state)
|
|
|
{
|
|
|
uint32_t val;
|
|
|
|
|
|
+ if (!intel_display_power_enabled(dev_priv, POWER_DOMAIN_PLLS))
|
|
|
+ return false;
|
|
|
+
|
|
|
val = I915_READ(PCH_DPLL(pll->id));
|
|
|
hw_state->dpll = val;
|
|
|
hw_state->fp0 = I915_READ(PCH_FP0(pll->id));
|
|
@@ -11359,7 +11401,9 @@ static void intel_shared_dpll_init(struct drm_device *dev)
|
|
|
{
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
- if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
|
|
|
+ if (HAS_DDI(dev))
|
|
|
+ intel_ddi_pll_init(dev);
|
|
|
+ else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
|
|
|
ibx_pch_dpll_init(dev);
|
|
|
else
|
|
|
dev_priv->num_shared_dpll = 0;
|
|
@@ -11398,9 +11442,11 @@ intel_primary_plane_disable(struct drm_plane *plane)
|
|
|
intel_disable_primary_hw_plane(dev_priv, intel_plane->plane,
|
|
|
intel_plane->pipe);
|
|
|
disable_unpin:
|
|
|
- i915_gem_track_fb(to_intel_framebuffer(plane->fb)->obj, NULL,
|
|
|
+ mutex_lock(&dev->struct_mutex);
|
|
|
+ i915_gem_track_fb(intel_fb_obj(plane->fb), NULL,
|
|
|
INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe));
|
|
|
- intel_unpin_fb_obj(to_intel_framebuffer(plane->fb)->obj);
|
|
|
+ intel_unpin_fb_obj(intel_fb_obj(plane->fb));
|
|
|
+ mutex_unlock(&dev->struct_mutex);
|
|
|
plane->fb = NULL;
|
|
|
|
|
|
return 0;
|
|
@@ -11417,7 +11463,8 @@ intel_primary_plane_setplane(struct drm_plane *plane, struct drm_crtc *crtc,
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
struct intel_plane *intel_plane = to_intel_plane(plane);
|
|
|
- struct drm_i915_gem_object *obj, *old_obj = NULL;
|
|
|
+ struct drm_i915_gem_object *obj = intel_fb_obj(fb);
|
|
|
+ struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb);
|
|
|
struct drm_rect dest = {
|
|
|
/* integer pixels */
|
|
|
.x1 = crtc_x,
|
|
@@ -11449,10 +11496,6 @@ intel_primary_plane_setplane(struct drm_plane *plane, struct drm_crtc *crtc,
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
|
- if (plane->fb)
|
|
|
- old_obj = to_intel_framebuffer(plane->fb)->obj;
|
|
|
- obj = to_intel_framebuffer(fb)->obj;
|
|
|
-
|
|
|
/*
|
|
|
* If the CRTC isn't enabled, we're just pinning the framebuffer,
|
|
|
* updating the fb pointer, and returning without touching the
|
|
@@ -11460,6 +11503,8 @@ intel_primary_plane_setplane(struct drm_plane *plane, struct drm_crtc *crtc,
|
|
|
* turn on the display with all planes setup as desired.
|
|
|
*/
|
|
|
if (!crtc->enabled) {
|
|
|
+ mutex_lock(&dev->struct_mutex);
|
|
|
+
|
|
|
/*
|
|
|
* If we already called setplane while the crtc was disabled,
|
|
|
* we may have an fb pinned; unpin it.
|
|
@@ -11471,7 +11516,10 @@ intel_primary_plane_setplane(struct drm_plane *plane, struct drm_crtc *crtc,
|
|
|
INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe));
|
|
|
|
|
|
/* Pin and return without programming hardware */
|
|
|
- return intel_pin_and_fence_fb_obj(dev, obj, NULL);
|
|
|
+ ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
|
|
|
+ mutex_unlock(&dev->struct_mutex);
|
|
|
+
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
intel_crtc_wait_for_pending_flips(crtc);
|
|
@@ -11483,14 +11531,18 @@ intel_primary_plane_setplane(struct drm_plane *plane, struct drm_crtc *crtc,
|
|
|
* because plane->fb still gets set and pinned.
|
|
|
*/
|
|
|
if (!visible) {
|
|
|
+ mutex_lock(&dev->struct_mutex);
|
|
|
+
|
|
|
/*
|
|
|
* Try to pin the new fb first so that we can bail out if we
|
|
|
* fail.
|
|
|
*/
|
|
|
if (plane->fb != fb) {
|
|
|
ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
|
|
|
- if (ret)
|
|
|
+ if (ret) {
|
|
|
+ mutex_unlock(&dev->struct_mutex);
|
|
|
return ret;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
i915_gem_track_fb(old_obj, obj,
|
|
@@ -11506,6 +11558,8 @@ intel_primary_plane_setplane(struct drm_plane *plane, struct drm_crtc *crtc,
|
|
|
if (plane->fb)
|
|
|
intel_unpin_fb_obj(old_obj);
|
|
|
|
|
|
+ mutex_unlock(&dev->struct_mutex);
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -12159,7 +12213,7 @@ static void intel_init_display(struct drm_device *dev)
|
|
|
dev_priv->display.crtc_mode_set = haswell_crtc_mode_set;
|
|
|
dev_priv->display.crtc_enable = haswell_crtc_enable;
|
|
|
dev_priv->display.crtc_disable = haswell_crtc_disable;
|
|
|
- dev_priv->display.off = haswell_crtc_off;
|
|
|
+ dev_priv->display.off = ironlake_crtc_off;
|
|
|
dev_priv->display.update_primary_plane =
|
|
|
ironlake_update_primary_plane;
|
|
|
} else if (HAS_PCH_SPLIT(dev)) {
|
|
@@ -12426,6 +12480,9 @@ void intel_modeset_init_hw(struct drm_device *dev)
|
|
|
{
|
|
|
intel_prepare_ddi(dev);
|
|
|
|
|
|
+ if (IS_VALLEYVIEW(dev))
|
|
|
+ vlv_update_cdclk(dev);
|
|
|
+
|
|
|
intel_init_clock_gating(dev);
|
|
|
|
|
|
intel_reset_dpio(dev);
|
|
@@ -12502,7 +12559,6 @@ void intel_modeset_init(struct drm_device *dev)
|
|
|
intel_init_dpio(dev);
|
|
|
intel_reset_dpio(dev);
|
|
|
|
|
|
- intel_cpu_pll_init(dev);
|
|
|
intel_shared_dpll_init(dev);
|
|
|
|
|
|
/* Just disable it once at startup */
|
|
@@ -12811,10 +12867,6 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
|
|
|
crtc->active ? "enabled" : "disabled");
|
|
|
}
|
|
|
|
|
|
- /* FIXME: Smash this into the new shared dpll infrastructure. */
|
|
|
- if (HAS_DDI(dev))
|
|
|
- intel_ddi_setup_hw_pll_state(dev);
|
|
|
-
|
|
|
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
|
|
|
struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
|
|
|
|
|
@@ -12828,6 +12880,9 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
|
|
|
|
|
|
DRM_DEBUG_KMS("%s hw state readout: refcount %i, on %i\n",
|
|
|
pll->name, pll->refcount, pll->on);
|
|
|
+
|
|
|
+ if (pll->refcount)
|
|
|
+ intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS);
|
|
|
}
|
|
|
|
|
|
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
|
|
@@ -12945,7 +13000,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
|
|
|
void intel_modeset_gem_init(struct drm_device *dev)
|
|
|
{
|
|
|
struct drm_crtc *c;
|
|
|
- struct intel_framebuffer *fb;
|
|
|
+ struct drm_i915_gem_object *obj;
|
|
|
|
|
|
mutex_lock(&dev->struct_mutex);
|
|
|
intel_init_gt_powersave(dev);
|
|
@@ -12962,11 +13017,11 @@ void intel_modeset_gem_init(struct drm_device *dev)
|
|
|
*/
|
|
|
mutex_lock(&dev->struct_mutex);
|
|
|
for_each_crtc(dev, c) {
|
|
|
- if (!c->primary->fb)
|
|
|
+ obj = intel_fb_obj(c->primary->fb);
|
|
|
+ if (obj == NULL)
|
|
|
continue;
|
|
|
|
|
|
- fb = to_intel_framebuffer(c->primary->fb);
|
|
|
- if (intel_pin_and_fence_fb_obj(dev, fb->obj, NULL)) {
|
|
|
+ if (intel_pin_and_fence_fb_obj(dev, obj, NULL)) {
|
|
|
DRM_ERROR("failed to pin boot fb on pipe %d\n",
|
|
|
to_intel_crtc(c)->pipe);
|
|
|
drm_framebuffer_unreference(c->primary->fb);
|