diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 413 |
1 files changed, 245 insertions, 168 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8c239f2d6bcd..6b4139064f9c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -384,28 +384,6 @@ out_unlock: return val; } -static void intel_dpio_write(struct drm_i915_private *dev_priv, int reg, - u32 val) -{ - unsigned long flags; - - spin_lock_irqsave(&dev_priv->dpio_lock, flags); - if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100)) { - DRM_ERROR("DPIO idle wait timed out\n"); - goto out_unlock; - } - - I915_WRITE(DPIO_DATA, val); - I915_WRITE(DPIO_REG, reg); - I915_WRITE(DPIO_PKT, DPIO_RID | DPIO_OP_WRITE | DPIO_PORTID | - DPIO_BYTE); - if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100)) - DRM_ERROR("DPIO write wait timed out\n"); - -out_unlock: - spin_unlock_irqrestore(&dev_priv->dpio_lock, flags); -} - static void vlv_init_dpio(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -911,26 +889,28 @@ static void assert_pll(struct drm_i915_private *dev_priv, /* For ILK+ */ static void assert_pch_pll(struct drm_i915_private *dev_priv, - enum pipe pipe, bool state) + struct intel_crtc *intel_crtc, bool state) { int reg; u32 val; bool cur_state; + if (!intel_crtc->pch_pll) { + WARN(1, "asserting PCH PLL enabled with no PLL\n"); + return; + } + if (HAS_PCH_CPT(dev_priv->dev)) { u32 pch_dpll; pch_dpll = I915_READ(PCH_DPLL_SEL); /* Make sure the selected PLL is enabled to the transcoder */ - WARN(!((pch_dpll >> (4 * pipe)) & 8), - "transcoder %d PLL not enabled\n", pipe); - - /* Convert the transcoder pipe number to a pll pipe number */ - pipe = (pch_dpll >> (4 * pipe)) & 1; + WARN(!((pch_dpll >> (4 * intel_crtc->pipe)) & 8), + "transcoder %d PLL not enabled\n", intel_crtc->pipe); } - reg = PCH_DPLL(pipe); + reg = intel_crtc->pch_pll->pll_reg; val = I915_READ(reg); cur_state = !!(val & DPLL_VCO_ENABLE); WARN(cur_state != state, @@ -1306,60 +1286,79 @@ static void intel_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) * The PCH PLL needs to be enabled before the PCH transcoder, since it * drives the transcoder clock. */ -static void intel_enable_pch_pll(struct drm_i915_private *dev_priv, - enum pipe pipe) +static void intel_enable_pch_pll(struct intel_crtc *intel_crtc) { + struct drm_i915_private *dev_priv = intel_crtc->base.dev->dev_private; + struct intel_pch_pll *pll = intel_crtc->pch_pll; int reg; u32 val; - if (pipe > 1) - return; - /* PCH only available on ILK+ */ BUG_ON(dev_priv->info->gen < 5); + BUG_ON(pll == NULL); + BUG_ON(pll->refcount == 0); + + DRM_DEBUG_KMS("enable PCH PLL %x (active %d, on? %d)for crtc %d\n", + pll->pll_reg, pll->active, pll->on, + intel_crtc->base.base.id); /* PCH refclock must be enabled first */ assert_pch_refclk_enabled(dev_priv); - reg = PCH_DPLL(pipe); + if (pll->active++ && pll->on) { + assert_pch_pll_enabled(dev_priv, intel_crtc); + return; + } + + DRM_DEBUG_KMS("enabling PCH PLL %x\n", pll->pll_reg); + + reg = pll->pll_reg; val = I915_READ(reg); val |= DPLL_VCO_ENABLE; I915_WRITE(reg, val); POSTING_READ(reg); udelay(200); + + pll->on = true; } -static void intel_disable_pch_pll(struct drm_i915_private *dev_priv, - enum pipe pipe) +static void intel_disable_pch_pll(struct intel_crtc *intel_crtc) { + struct drm_i915_private *dev_priv = intel_crtc->base.dev->dev_private; + struct intel_pch_pll *pll = intel_crtc->pch_pll; int reg; - u32 val, pll_mask = TRANSC_DPLL_ENABLE | TRANSC_DPLLB_SEL, - pll_sel = TRANSC_DPLL_ENABLE; - - if (pipe > 1) - return; + u32 val; /* PCH only available on ILK+ */ BUG_ON(dev_priv->info->gen < 5); + if (pll == NULL) + return; - /* Make sure transcoder isn't still depending on us */ - assert_transcoder_disabled(dev_priv, pipe); + BUG_ON(pll->refcount == 0); - if (pipe == 0) - pll_sel |= TRANSC_DPLLA_SEL; - else if (pipe == 1) - pll_sel |= TRANSC_DPLLB_SEL; + DRM_DEBUG_KMS("disable PCH PLL %x (active %d, on? %d) for crtc %d\n", + pll->pll_reg, pll->active, pll->on, + intel_crtc->base.base.id); - - if ((I915_READ(PCH_DPLL_SEL) & pll_mask) == pll_sel) + BUG_ON(pll->active == 0); + if (--pll->active) { + assert_pch_pll_enabled(dev_priv, intel_crtc); return; + } + + DRM_DEBUG_KMS("disabling PCH PLL %x\n", pll->pll_reg); + + /* Make sure transcoder isn't still depending on us */ + assert_transcoder_disabled(dev_priv, intel_crtc->pipe); - reg = PCH_DPLL(pipe); + reg = pll->pll_reg; val = I915_READ(reg); val &= ~DPLL_VCO_ENABLE; I915_WRITE(reg, val); POSTING_READ(reg); udelay(200); + + pll->on = false; } static void intel_enable_transcoder(struct drm_i915_private *dev_priv, @@ -1373,7 +1372,7 @@ static void intel_enable_transcoder(struct drm_i915_private *dev_priv, BUG_ON(dev_priv->info->gen < 5); /* Make sure PCH DPLL is enabled */ - assert_pch_pll_enabled(dev_priv, pipe); + assert_pch_pll_enabled(dev_priv, to_intel_crtc(crtc)); /* FDI must be feeding us bits for PCH ports */ assert_fdi_tx_enabled(dev_priv, pipe); @@ -2507,26 +2506,6 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc) udelay(100); } -/* - * When we disable a pipe, we need to clear any pending scanline wait events - * to avoid hanging the ring, which we assume we are waiting on. - */ -static void intel_clear_scanline_wait(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_ring_buffer *ring; - u32 tmp; - - if (IS_GEN2(dev)) - /* Can't break the hang on i8xx */ - return; - - ring = LP_RING(dev_priv); - tmp = I915_READ_CTL(ring); - if (tmp & RING_WAIT) - I915_WRITE_CTL(ring, tmp); -} - static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -2578,29 +2557,36 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int pipe = intel_crtc->pipe; - u32 reg, temp, transc_sel; + u32 reg, temp; /* For PCH output, training FDI link */ dev_priv->display.fdi_link_train(crtc); - intel_enable_pch_pll(dev_priv, pipe); + intel_enable_pch_pll(intel_crtc); if (HAS_PCH_CPT(dev)) { - transc_sel = intel_crtc->use_pll_a ? TRANSC_DPLLA_SEL : - TRANSC_DPLLB_SEL; + u32 sel; - /* Be sure PCH DPLL SEL is set */ temp = I915_READ(PCH_DPLL_SEL); - if (pipe == 0) { - temp &= ~(TRANSA_DPLLB_SEL); - temp |= (TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL); - } else if (pipe == 1) { - temp &= ~(TRANSB_DPLLB_SEL); - temp |= (TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL); - } else if (pipe == 2) { - temp &= ~(TRANSC_DPLLB_SEL); - temp |= (TRANSC_DPLL_ENABLE | transc_sel); + switch (pipe) { + default: + case 0: + temp |= TRANSA_DPLL_ENABLE; + sel = TRANSA_DPLLB_SEL; + break; + case 1: + temp |= TRANSB_DPLL_ENABLE; + sel = TRANSB_DPLLB_SEL; + break; + case 2: + temp |= TRANSC_DPLL_ENABLE; + sel = TRANSC_DPLLB_SEL; + break; } + if (intel_crtc->pch_pll->pll_reg == _PCH_DPLL_B) + temp |= sel; + else + temp &= ~sel; I915_WRITE(PCH_DPLL_SEL, temp); } @@ -2658,6 +2644,82 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) intel_enable_transcoder(dev_priv, pipe); } +static void intel_put_pch_pll(struct intel_crtc *intel_crtc) +{ + struct intel_pch_pll *pll = intel_crtc->pch_pll; + + if (pll == NULL) + return; + + if (pll->refcount == 0) { + WARN(1, "bad PCH PLL refcount\n"); + return; + } + + --pll->refcount; + intel_crtc->pch_pll = NULL; +} + +static struct intel_pch_pll *intel_get_pch_pll(struct intel_crtc *intel_crtc, u32 dpll, u32 fp) +{ + struct drm_i915_private *dev_priv = intel_crtc->base.dev->dev_private; + struct intel_pch_pll *pll; + int i; + + pll = intel_crtc->pch_pll; + if (pll) { + DRM_DEBUG_KMS("CRTC:%d reusing existing PCH PLL %x\n", + intel_crtc->base.base.id, pll->pll_reg); + goto prepare; + } + + for (i = 0; i < dev_priv->num_pch_pll; i++) { + pll = &dev_priv->pch_plls[i]; + + /* Only want to check enabled timings first */ + if (pll->refcount == 0) + continue; + + if (dpll == (I915_READ(pll->pll_reg) & 0x7fffffff) && + fp == I915_READ(pll->fp0_reg)) { + DRM_DEBUG_KMS("CRTC:%d sharing existing PCH PLL %x (refcount %d, ative %d)\n", + intel_crtc->base.base.id, + pll->pll_reg, pll->refcount, pll->active); + + goto found; + } + } + + /* Ok no matching timings, maybe there's a free one? */ + for (i = 0; i < dev_priv->num_pch_pll; i++) { + pll = &dev_priv->pch_plls[i]; + if (pll->refcount == 0) { + DRM_DEBUG_KMS("CRTC:%d allocated PCH PLL %x\n", + intel_crtc->base.base.id, pll->pll_reg); + goto found; + } + } + + return NULL; + +found: + intel_crtc->pch_pll = pll; + pll->refcount++; + DRM_DEBUG_DRIVER("using pll %d for pipe %d\n", i, intel_crtc->pipe); +prepare: /* separate function? */ + DRM_DEBUG_DRIVER("switching PLL %x off\n", pll->pll_reg); + + /* Wait for the clocks to stabilize before rewriting the regs */ + I915_WRITE(pll->pll_reg, dpll & ~DPLL_VCO_ENABLE); + POSTING_READ(pll->pll_reg); + udelay(150); + + I915_WRITE(pll->fp0_reg, fp); + I915_WRITE(pll->pll_reg, dpll & ~DPLL_VCO_ENABLE); + pll->on = false; + return pll; +} + void intel_cpt_verify_modeset(struct drm_device *dev, int pipe) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -2802,8 +2864,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) } /* disable PCH DPLL */ - if (!intel_crtc->no_pll) - intel_disable_pch_pll(dev_priv, pipe); + intel_disable_pch_pll(intel_crtc); /* Switch from PCDclk to Rawclk */ reg = FDI_RX_CTL(pipe); @@ -2831,7 +2892,6 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) mutex_lock(&dev->struct_mutex); intel_update_fbc(dev); - intel_clear_scanline_wait(dev); mutex_unlock(&dev->struct_mutex); } @@ -2859,6 +2919,12 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) } } +static void ironlake_crtc_off(struct drm_crtc *crtc) +{ + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + intel_put_pch_pll(intel_crtc); +} + static void intel_crtc_dpms_overlay(struct intel_crtc *intel_crtc, bool enable) { if (!enable && intel_crtc->overlay) { @@ -2930,7 +2996,6 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) intel_crtc->active = false; intel_update_fbc(dev); intel_update_watermarks(dev); - intel_clear_scanline_wait(dev); } static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) @@ -2950,6 +3015,10 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) } } +static void i9xx_crtc_off(struct drm_crtc *crtc) +{ +} + /** * Sets the power management mode of the pipe and plane. */ @@ -2997,8 +3066,11 @@ static void intel_crtc_disable(struct drm_crtc *crtc) { struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); + dev_priv->display.off(crtc); + assert_plane_disabled(dev->dev_private, to_intel_crtc(crtc)->plane); assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe); @@ -3822,7 +3894,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, I915_WRITE(DSPCNTR(plane), dspcntr); POSTING_READ(DSPCNTR(plane)); - intel_enable_plane(dev_priv, plane, pipe); ret = intel_pipe_set_base(crtc, x, y, old_fb); @@ -4241,29 +4312,18 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, DRM_DEBUG_KMS("Mode for pipe %d:\n", pipe); drm_mode_debug_printmodeline(mode); - /* PCH eDP needs FDI, but CPU eDP does not */ - if (!intel_crtc->no_pll) { - if (!is_cpu_edp) { - I915_WRITE(PCH_FP0(pipe), fp); - I915_WRITE(PCH_DPLL(pipe), dpll & ~DPLL_VCO_ENABLE); + /* CPU eDP is the only output that doesn't need a PCH PLL of its own */ + if (!is_cpu_edp) { + struct intel_pch_pll *pll; - POSTING_READ(PCH_DPLL(pipe)); - udelay(150); - } - } else { - if (dpll == (I915_READ(PCH_DPLL(0)) & 0x7fffffff) && - fp == I915_READ(PCH_FP0(0))) { - intel_crtc->use_pll_a = true; - DRM_DEBUG_KMS("using pipe a dpll\n"); - } else if (dpll == (I915_READ(PCH_DPLL(1)) & 0x7fffffff) && - fp == I915_READ(PCH_FP0(1))) { - intel_crtc->use_pll_a = false; - DRM_DEBUG_KMS("using pipe b dpll\n"); - } else { - DRM_DEBUG_KMS("no matching PLL configuration for pipe 2\n"); + pll = intel_get_pch_pll(intel_crtc, dpll, fp); + if (pll == NULL) { + DRM_DEBUG_DRIVER("failed to find PLL for pipe %d\n", + pipe); return -EINVAL; } - } + } else + intel_put_pch_pll(intel_crtc); /* The LVDS pin pair needs to be on before the DPLLs are enabled. * This is an exception to the general rule that mode_set doesn't turn @@ -4320,11 +4380,11 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, I915_WRITE(TRANSDPLINK_N1(pipe), 0); } - if (!intel_crtc->no_pll && (!edp_encoder || is_pch_edp)) { - I915_WRITE(PCH_DPLL(pipe), dpll); + if (intel_crtc->pch_pll) { + I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll); /* Wait for the clocks to stabilize. */ - POSTING_READ(PCH_DPLL(pipe)); + POSTING_READ(intel_crtc->pch_pll->pll_reg); udelay(150); /* The pixel multiplier can only be updated once the @@ -4332,20 +4392,20 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, * * So write it again. */ - I915_WRITE(PCH_DPLL(pipe), dpll); + I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll); } intel_crtc->lowfreq_avail = false; - if (!intel_crtc->no_pll) { + if (intel_crtc->pch_pll) { if (is_lvds && has_reduced_clock && i915_powersave) { - I915_WRITE(PCH_FP1(pipe), fp2); + I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp2); intel_crtc->lowfreq_avail = true; if (HAS_PIPE_CXSR(dev)) { DRM_DEBUG_KMS("enabling CxSR downclocking\n"); pipeconf |= PIPECONF_CXSR_DOWNCLOCK; } } else { - I915_WRITE(PCH_FP1(pipe), fp); + I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp); if (HAS_PIPE_CXSR(dev)) { DRM_DEBUG_KMS("disabling CxSR downclocking\n"); pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK; @@ -4777,9 +4837,6 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc, else i9xx_update_cursor(crtc, base); } - - if (visible) - intel_mark_busy(dev, to_intel_framebuffer(crtc->fb)->obj); } static int intel_crtc_cursor_set(struct drm_crtc *crtc, @@ -5303,7 +5360,6 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1; drm_mode_set_name(mode); - drm_mode_set_crtcinfo(mode, 0); return mode; } @@ -5475,9 +5531,10 @@ void intel_mark_busy(struct drm_device *dev, struct drm_i915_gem_object *obj) if (!drm_core_check_feature(dev, DRIVER_MODESET)) return; - if (!dev_priv->busy) + if (!dev_priv->busy) { + intel_sanitize_pm(dev); dev_priv->busy = true; - else + } else mod_timer(&dev_priv->idle_timer, jiffies + msecs_to_jiffies(GPU_IDLE_TIMEOUT)); @@ -5653,16 +5710,17 @@ static int intel_gen2_queue_flip(struct drm_device *dev, struct intel_crtc *intel_crtc = to_intel_crtc(crtc); unsigned long offset; u32 flip_mask; + struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; int ret; - ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv)); + ret = intel_pin_and_fence_fb_obj(dev, obj, ring); if (ret) goto err; /* Offset into the new buffer for cases of shared fbs between CRTCs */ offset = crtc->y * fb->pitches[0] + crtc->x * fb->bits_per_pixel/8; - ret = BEGIN_LP_RING(6); + ret = intel_ring_begin(ring, 6); if (ret) goto err_unpin; @@ -5673,14 +5731,14 @@ static int intel_gen2_queue_flip(struct drm_device *dev, flip_mask = MI_WAIT_FOR_PLANE_B_FLIP; else flip_mask = MI_WAIT_FOR_PLANE_A_FLIP; - OUT_RING(MI_WAIT_FOR_EVENT | flip_mask); - OUT_RING(MI_NOOP); - OUT_RING(MI_DISPLAY_FLIP | - MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); - OUT_RING(fb->pitches[0]); - OUT_RING(obj->gtt_offset + offset); - OUT_RING(0); /* aux display base address, unused */ - ADVANCE_LP_RING(); + intel_ring_emit(ring, MI_WAIT_FOR_EVENT | flip_mask); + intel_ring_emit(ring, MI_NOOP); + intel_ring_emit(ring, MI_DISPLAY_FLIP | + MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); + intel_ring_emit(ring, fb->pitches[0]); + intel_ring_emit(ring, obj->gtt_offset + offset); + intel_ring_emit(ring, 0); /* aux display base address, unused */ + intel_ring_advance(ring); return 0; err_unpin: @@ -5698,16 +5756,17 @@ static int intel_gen3_queue_flip(struct drm_device *dev, struct intel_crtc *intel_crtc = to_intel_crtc(crtc); unsigned long offset; u32 flip_mask; + struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; int ret; - ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv)); + ret = intel_pin_and_fence_fb_obj(dev, obj, ring); if (ret) goto err; /* Offset into the new buffer for cases of shared fbs between CRTCs */ offset = crtc->y * fb->pitches[0] + crtc->x * fb->bits_per_pixel/8; - ret = BEGIN_LP_RING(6); + ret = intel_ring_begin(ring, 6); if (ret) goto err_unpin; @@ -5715,15 +5774,15 @@ static int intel_gen3_queue_flip(struct drm_device *dev, flip_mask = MI_WAIT_FOR_PLANE_B_FLIP; else flip_mask = MI_WAIT_FOR_PLANE_A_FLIP; - OUT_RING(MI_WAIT_FOR_EVENT | flip_mask); - OUT_RING(MI_NOOP); - OUT_RING(MI_DISPLAY_FLIP_I915 | - MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); - OUT_RING(fb->pitches[0]); - OUT_RING(obj->gtt_offset + offset); - OUT_RING(MI_NOOP); - - ADVANCE_LP_RING(); + intel_ring_emit(ring, MI_WAIT_FOR_EVENT | flip_mask); + intel_ring_emit(ring, MI_NOOP); + intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | + MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); + intel_ring_emit(ring, fb->pitches[0]); + intel_ring_emit(ring, obj->gtt_offset + offset); + intel_ring_emit(ring, MI_NOOP); + + intel_ring_advance(ring); return 0; err_unpin: @@ -5740,13 +5799,14 @@ static int intel_gen4_queue_flip(struct drm_device *dev, struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); uint32_t pf, pipesrc; + struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; int ret; - ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv)); + ret = intel_pin_and_fence_fb_obj(dev, obj, ring); if (ret) goto err; - ret = BEGIN_LP_RING(4); + ret = intel_ring_begin(ring, 4); if (ret) goto err_unpin; @@ -5754,10 +5814,10 @@ static int intel_gen4_queue_flip(struct drm_device *dev, * Display Registers (which do not change across a page-flip) * so we need only reprogram the base address. */ - OUT_RING(MI_DISPLAY_FLIP | - MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); - OUT_RING(fb->pitches[0]); - OUT_RING(obj->gtt_offset | obj->tiling_mode); + intel_ring_emit(ring, MI_DISPLAY_FLIP | + MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); + intel_ring_emit(ring, fb->pitches[0]); + intel_ring_emit(ring, obj->gtt_offset | obj->tiling_mode); /* XXX Enabling the panel-fitter across page-flip is so far * untested on non-native modes, so ignore it for now. @@ -5765,8 +5825,8 @@ static int intel_gen4_queue_flip(struct drm_device *dev, */ pf = 0; pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff; - OUT_RING(pf | pipesrc); - ADVANCE_LP_RING(); + intel_ring_emit(ring, pf | pipesrc); + intel_ring_advance(ring); return 0; err_unpin: @@ -5782,21 +5842,22 @@ static int intel_gen6_queue_flip(struct drm_device *dev, { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; uint32_t pf, pipesrc; int ret; - ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv)); + ret = intel_pin_and_fence_fb_obj(dev, obj, ring); if (ret) goto err; - ret = BEGIN_LP_RING(4); + ret = intel_ring_begin(ring, 4); if (ret) goto err_unpin; - OUT_RING(MI_DISPLAY_FLIP | - MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); - OUT_RING(fb->pitches[0] | obj->tiling_mode); - OUT_RING(obj->gtt_offset); + intel_ring_emit(ring, MI_DISPLAY_FLIP | + MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); + intel_ring_emit(ring, fb->pitches[0] | obj->tiling_mode); + intel_ring_emit(ring, obj->gtt_offset); /* Contrary to the suggestions in the documentation, * "Enable Panel Fitter" does not seem to be required when page @@ -5806,8 +5867,8 @@ static int intel_gen6_queue_flip(struct drm_device *dev, */ pf = 0; pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff; - OUT_RING(pf | pipesrc); - ADVANCE_LP_RING(); + intel_ring_emit(ring, pf | pipesrc); + intel_ring_advance(ring); return 0; err_unpin: @@ -6027,6 +6088,23 @@ static const struct drm_crtc_funcs intel_crtc_funcs = { .page_flip = intel_crtc_page_flip, }; +static void intel_pch_pll_init(struct drm_device *dev) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + int i; + + if (dev_priv->num_pch_pll == 0) { + DRM_DEBUG_KMS("No PCH PLLs on this hardware, skipping initialisation\n"); + return; + } + + for (i = 0; i < dev_priv->num_pch_pll; i++) { + dev_priv->pch_plls[i].pll_reg = _PCH_DPLL(i); + dev_priv->pch_plls[i].fp0_reg = _PCH_FP0(i); + dev_priv->pch_plls[i].fp1_reg = _PCH_FP1(i); + } +} + static void intel_crtc_init(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = dev->dev_private; @@ -6064,8 +6142,6 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) intel_crtc->bpp = 24; /* default for pre-Ironlake */ if (HAS_PCH_SPLIT(dev)) { - if (pipe == 2 && IS_IVYBRIDGE(dev)) - intel_crtc->no_pll = true; intel_helper_funcs.prepare = ironlake_crtc_prepare; intel_helper_funcs.commit = ironlake_crtc_commit; } else { @@ -6084,15 +6160,12 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, struct drm_file *file) { - drm_i915_private_t *dev_priv = dev->dev_private; struct drm_i915_get_pipe_from_crtc_id *pipe_from_crtc_id = data; struct drm_mode_object *drmmode_obj; struct intel_crtc *crtc; - if (!dev_priv) { - DRM_ERROR("called with no initialization\n"); - return -EINVAL; - } + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + return -ENODEV; drmmode_obj = drm_mode_object_find(dev, pipe_from_crtc_id->crtc_id, DRM_MODE_OBJECT_CRTC); @@ -6348,10 +6421,12 @@ static void intel_init_display(struct drm_device *dev) if (HAS_PCH_SPLIT(dev)) { dev_priv->display.dpms = ironlake_crtc_dpms; dev_priv->display.crtc_mode_set = ironlake_crtc_mode_set; + dev_priv->display.off = ironlake_crtc_off; dev_priv->display.update_plane = ironlake_update_plane; } else { dev_priv->display.dpms = i9xx_crtc_dpms; dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set; + dev_priv->display.off = i9xx_crtc_off; dev_priv->display.update_plane = i9xx_update_plane; } @@ -6614,6 +6689,8 @@ void intel_modeset_init(struct drm_device *dev) DRM_DEBUG_KMS("plane %d init failed: %d\n", i, ret); } + intel_pch_pll_init(dev); + /* Just disable it once at startup */ i915_disable_vga(dev); intel_setup_outputs(dev); |