X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=drivers%2Fgpu%2Fdrm%2Fi915%2Fintel_display.c;h=930746527e9d8c0e46a4ed0ce0e48aa0b7d8dbe2;hb=75f7f3ec600524c9544cc31695155f1a9ddbe1d9;hp=5b586e9cb8de2ac7bb2daf98bb9db63904ef432e;hpb=7895a81dcfc23b9fa89a0f4f75af7abf7c6c71ed;p=firefly-linux-kernel-4.4.55.git diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5b586e9cb8de..930746527e9d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -58,6 +58,15 @@ static int intel_framebuffer_init(struct drm_device *dev, struct intel_framebuffer *ifb, struct drm_mode_fb_cmd2 *mode_cmd, struct drm_i915_gem_object *obj); +static void intel_dp_set_m_n(struct intel_crtc *crtc); +static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc); +static void intel_set_pipe_timings(struct intel_crtc *intel_crtc); +static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc, + struct intel_link_m_n *m_n); +static void ironlake_set_pipeconf(struct drm_crtc *crtc); +static void haswell_set_pipeconf(struct drm_crtc *crtc); +static void intel_set_pipe_csc(struct drm_crtc *crtc); +static void vlv_prepare_pll(struct intel_crtc *crtc); typedef struct { int min, max; @@ -962,7 +971,7 @@ bool ibx_digital_port_connected(struct drm_i915_private *dev_priv, u32 bit; if (HAS_PCH_IBX(dev_priv->dev)) { - switch(port->port) { + switch (port->port) { case PORT_B: bit = SDE_PORTB_HOTPLUG; break; @@ -976,7 +985,7 @@ bool ibx_digital_port_connected(struct drm_i915_private *dev_priv, return true; } } else { - switch(port->port) { + switch (port->port) { case PORT_B: bit = SDE_PORTB_HOTPLUG_CPT; break; @@ -1181,10 +1190,8 @@ static void assert_cursor(struct drm_i915_private *dev_priv, if (IS_845G(dev) || IS_I865G(dev)) cur_state = I915_READ(_CURACNTR) & CURSOR_ENABLE; - else if (INTEL_INFO(dev)->gen <= 6 || IS_VALLEYVIEW(dev)) - cur_state = I915_READ(CURCNTR(pipe)) & CURSOR_MODE; else - cur_state = I915_READ(CURCNTR_IVB(pipe)) & CURSOR_MODE; + cur_state = I915_READ(CURCNTR(pipe)) & CURSOR_MODE; WARN(cur_state != state, "cursor on pipe %c assertion failure (expected %s, current %s)\n", @@ -1567,7 +1574,6 @@ static void chv_enable_pll(struct intel_crtc *crtc) struct drm_i915_private *dev_priv = dev->dev_private; int pipe = crtc->pipe; enum dpio_channel port = vlv_pipe_to_channel(pipe); - int dpll = DPLL(crtc->pipe); u32 tmp; assert_pipe_disabled(dev_priv, crtc->pipe); @@ -1587,19 +1593,15 @@ static void chv_enable_pll(struct intel_crtc *crtc) udelay(1); /* Enable PLL */ - tmp = I915_READ(dpll); - tmp |= DPLL_VCO_ENABLE; - I915_WRITE(dpll, tmp); + I915_WRITE(DPLL(pipe), crtc->config.dpll_hw_state.dpll); /* Check PLL is locked */ - if (wait_for(((I915_READ(dpll) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1)) + if (wait_for(((I915_READ(DPLL(pipe)) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1)) DRM_ERROR("PLL %d failed to lock\n", pipe); - /* Deassert soft data lane reset*/ - tmp = vlv_dpio_read(dev_priv, pipe, VLV_PCS_DW0(port)); - tmp |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); - vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port), tmp); - + /* not sure when this should be written */ + I915_WRITE(DPLL_MD(pipe), crtc->config.dpll_hw_state.dpll_md); + POSTING_READ(DPLL_MD(pipe)); mutex_unlock(&dev_priv->dpio_lock); } @@ -1692,14 +1694,27 @@ static void vlv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) static void chv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) { - int dpll = DPLL(pipe); + enum dpio_channel port = vlv_pipe_to_channel(pipe); u32 val; + /* Make sure the pipe isn't still relying on us */ + assert_pipe_disabled(dev_priv, pipe); + /* Set PLL en = 0 */ - val = I915_READ(dpll); - val &= ~DPLL_VCO_ENABLE; - I915_WRITE(dpll, val); + val = DPLL_SSC_REF_CLOCK_CHV; + if (pipe != PIPE_A) + val |= DPLL_INTEGRATED_CRI_CLK_VLV; + I915_WRITE(DPLL(pipe), val); + POSTING_READ(DPLL(pipe)); + mutex_lock(&dev_priv->dpio_lock); + + /* Disable 10bit clock to display controller */ + val = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW14(port)); + val &= ~DPIO_DCLKP_EN; + vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW14(port), val); + + mutex_unlock(&dev_priv->dpio_lock); } void vlv_wait_port_ready(struct drm_i915_private *dev_priv, @@ -1730,22 +1745,36 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv, port_name(dport->port), I915_READ(dpll_reg)); } +static void intel_prepare_shared_dpll(struct intel_crtc *crtc) +{ + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc); + + WARN_ON(!pll->refcount); + if (pll->active == 0) { + DRM_DEBUG_DRIVER("setting up %s\n", pll->name); + WARN_ON(pll->on); + assert_shared_dpll_disabled(dev_priv, pll); + + pll->mode_set(dev_priv, pll); + } +} + /** - * ironlake_enable_shared_dpll - enable PCH PLL + * intel_enable_shared_dpll - enable PCH PLL * @dev_priv: i915 private structure * @pipe: pipe PLL to enable * * The PCH PLL needs to be enabled before the PCH transcoder, since it * drives the transcoder clock. */ -static void ironlake_enable_shared_dpll(struct intel_crtc *crtc) +static void intel_enable_shared_dpll(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc); - /* PCH PLLs only available on ILK, SNB and IVB */ - BUG_ON(INTEL_INFO(dev)->gen < 5); if (WARN_ON(pll == NULL)) return; @@ -2312,7 +2341,7 @@ static void intel_find_plane_obj(struct intel_crtc *intel_crtc, * Failed to alloc the obj, check to see if we should share * an fb with another CRTC instead */ - list_for_each_entry(c, &dev->mode_config.crtc_list, head) { + for_each_crtc(dev, c) { i = to_intel_crtc(c); if (c == &intel_crtc->base) @@ -2330,9 +2359,9 @@ static void intel_find_plane_obj(struct intel_crtc *intel_crtc, } } -static int i9xx_update_primary_plane(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - int x, int y) +static void i9xx_update_primary_plane(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int x, int y) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -2418,13 +2447,11 @@ static int i9xx_update_primary_plane(struct drm_crtc *crtc, } else I915_WRITE(DSPADDR(plane), i915_gem_obj_ggtt_offset(obj) + linear_offset); POSTING_READ(reg); - - return 0; } -static int ironlake_update_primary_plane(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - int x, int y) +static void ironlake_update_primary_plane(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int x, int y) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -2502,8 +2529,6 @@ static int ironlake_update_primary_plane(struct drm_crtc *crtc, I915_WRITE(DSPLINOFF(plane), linear_offset); } POSTING_READ(reg); - - return 0; } /* Assume fb object is pinned & idle & fenced and just update base pointers */ @@ -2518,7 +2543,9 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, dev_priv->display.disable_fbc(dev); intel_increase_pllclock(crtc); - return dev_priv->display.update_primary_plane(crtc, fb, x, y); + dev_priv->display.update_primary_plane(crtc, fb, x, y); + + return 0; } void intel_display_handle_reset(struct drm_device *dev) @@ -2540,7 +2567,7 @@ void intel_display_handle_reset(struct drm_device *dev) * pending_flip_queue really got woken up. */ - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + for_each_crtc(dev, crtc) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); enum plane plane = intel_crtc->plane; @@ -2548,7 +2575,7 @@ void intel_display_handle_reset(struct drm_device *dev) intel_finish_page_flip_plane(dev, plane); } - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + for_each_crtc(dev, crtc) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); mutex_lock(&crtc->mutex); @@ -2677,14 +2704,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, intel_crtc->config.pipe_src_h = adjusted_mode->crtc_vdisplay; } - ret = dev_priv->display.update_primary_plane(crtc, fb, x, y); - if (ret) { - mutex_lock(&dev->struct_mutex); - intel_unpin_fb_obj(to_intel_framebuffer(fb)->obj); - mutex_unlock(&dev->struct_mutex); - DRM_ERROR("failed to update base address\n"); - return ret; - } + dev_priv->display.update_primary_plane(crtc, fb, x, y); old_fb = crtc->primary->fb; crtc->primary->fb = fb; @@ -3221,9 +3241,8 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc) udelay(100); /* Ironlake workaround, disable clock pointer after downing FDI */ - if (HAS_PCH_IBX(dev)) { + if (HAS_PCH_IBX(dev)) I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR); - } /* still set train pattern 1 */ reg = FDI_TX_CTL(pipe); @@ -3261,7 +3280,7 @@ bool intel_has_pending_fb_unpin(struct drm_device *dev) * cannot claim and pin a new fb without at least acquring the * struct_mutex and so serialising with us. */ - list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) { + for_each_intel_crtc(dev, crtc) { if (atomic_read(&crtc->unpin_work_count) == 0) continue; @@ -3284,8 +3303,9 @@ static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc) WARN_ON(waitqueue_active(&dev_priv->pending_flip_queue)); - wait_event(dev_priv->pending_flip_queue, - !intel_crtc_has_pending_flip(crtc)); + WARN_ON(wait_event_timeout(dev_priv->pending_flip_queue, + !intel_crtc_has_pending_flip(crtc), + 60*HZ) == 0); mutex_lock(&dev->struct_mutex); intel_finish_fb(crtc->primary->fb); @@ -3498,7 +3518,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) * Note that enable_shared_dpll tries to do the right thing, but * get_shared_dpll unconditionally resets the pll - we need that to have * the right LVDS enable sequence. */ - ironlake_enable_shared_dpll(intel_crtc); + intel_enable_shared_dpll(intel_crtc); /* set transcoder timing, panel must allow it */ assert_panel_unlocked(dev_priv, pipe); @@ -3602,6 +3622,8 @@ static struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc) DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n", crtc->base.base.id, pll->name); + WARN_ON(pll->refcount); + goto found; } @@ -3635,20 +3657,13 @@ static struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc) return NULL; found: + if (pll->refcount == 0) + pll->hw_state = crtc->config.dpll_hw_state; + crtc->config.shared_dpll = i; DRM_DEBUG_DRIVER("using %s for pipe %c\n", pll->name, pipe_name(crtc->pipe)); - if (pll->active == 0) { - memcpy(&pll->hw_state, &crtc->config.dpll_hw_state, - sizeof(pll->hw_state)); - - DRM_DEBUG_DRIVER("setting up %s\n", pll->name); - WARN_ON(pll->on); - assert_shared_dpll_disabled(dev_priv, pll); - - pll->mode_set(dev_priv, pll); - } pll->refcount++; return pll; @@ -3884,6 +3899,7 @@ static void intel_crtc_enable_planes(struct drm_crtc *crtc) mutex_lock(&dev->struct_mutex); intel_update_fbc(dev); + intel_edp_psr_update(dev); mutex_unlock(&dev->struct_mutex); } @@ -3916,12 +3932,35 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_encoder *encoder; int pipe = intel_crtc->pipe; + enum plane plane = intel_crtc->plane; WARN_ON(!crtc->enabled); if (intel_crtc->active) return; + if (intel_crtc->config.has_pch_encoder) + intel_prepare_shared_dpll(intel_crtc); + + if (intel_crtc->config.has_dp_encoder) + intel_dp_set_m_n(intel_crtc); + + intel_set_pipe_timings(intel_crtc); + + if (intel_crtc->config.has_pch_encoder) { + intel_cpu_transcoder_set_m_n(intel_crtc, + &intel_crtc->config.fdi_m_n); + } + + ironlake_set_pipeconf(crtc); + + /* Set up the display plane register */ + I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE); + POSTING_READ(DSPCNTR(plane)); + + dev_priv->display.update_primary_plane(crtc, crtc->primary->fb, + crtc->x, crtc->y); + intel_crtc->active = true; intel_set_cpu_fifo_underrun_reporting(dev, pipe, true); @@ -3993,7 +4032,7 @@ static void haswell_mode_set_planes_workaround(struct intel_crtc *crtc) /* We want to get the other_active_crtc only if there's only 1 other * active crtc. */ - list_for_each_entry(crtc_it, &dev->mode_config.crtc_list, base.head) { + for_each_intel_crtc(dev, crtc_it) { if (!crtc_it->active || crtc_it == crtc) continue; @@ -4016,12 +4055,34 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_encoder *encoder; int pipe = intel_crtc->pipe; + enum plane plane = intel_crtc->plane; WARN_ON(!crtc->enabled); if (intel_crtc->active) return; + if (intel_crtc->config.has_dp_encoder) + intel_dp_set_m_n(intel_crtc); + + intel_set_pipe_timings(intel_crtc); + + if (intel_crtc->config.has_pch_encoder) { + intel_cpu_transcoder_set_m_n(intel_crtc, + &intel_crtc->config.fdi_m_n); + } + + haswell_set_pipeconf(crtc); + + intel_set_pipe_csc(crtc); + + /* Set up the display plane register */ + I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE | DISPPLANE_PIPE_CSC_ENABLE); + POSTING_READ(DSPCNTR(plane)); + + dev_priv->display.update_primary_plane(crtc, crtc->primary->fb, + crtc->x, crtc->y); + intel_crtc->active = true; intel_set_cpu_fifo_underrun_reporting(dev, pipe, true); @@ -4140,6 +4201,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) mutex_lock(&dev->struct_mutex); intel_update_fbc(dev); + intel_edp_psr_update(dev); mutex_unlock(&dev->struct_mutex); } @@ -4187,6 +4249,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc) mutex_lock(&dev->struct_mutex); intel_update_fbc(dev); + intel_edp_psr_update(dev); mutex_unlock(&dev->struct_mutex); } @@ -4312,7 +4375,7 @@ static void modeset_update_crtc_power_domains(struct drm_device *dev) * First get all needed power domains, then put all unneeded, to avoid * any unnecessary toggling of the power wells. */ - list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) { + for_each_intel_crtc(dev, crtc) { enum intel_display_power_domain domain; if (!crtc->base.enabled) @@ -4324,7 +4387,7 @@ static void modeset_update_crtc_power_domains(struct drm_device *dev) intel_display_power_get(dev_priv, domain); } - list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) { + for_each_intel_crtc(dev, crtc) { enum intel_display_power_domain domain; for_each_power_domain(domain, crtc->enabled_power_domains) @@ -4458,8 +4521,7 @@ static int intel_mode_max_pixclk(struct drm_i915_private *dev_priv) struct intel_crtc *intel_crtc; int max_pixclk = 0; - list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, - base.head) { + for_each_intel_crtc(dev, intel_crtc) { if (intel_crtc->new_enabled) max_pixclk = max(max_pixclk, intel_crtc->new_config->adjusted_mode.crtc_clock); @@ -4480,8 +4542,7 @@ static void valleyview_modeset_global_pipes(struct drm_device *dev, return; /* disable/enable all currently active pipes while we change cdclk */ - list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, - base.head) + for_each_intel_crtc(dev, intel_crtc) if (intel_crtc->base.enabled) *prepare_pipes |= (1 << intel_crtc->pipe); } @@ -4504,13 +4565,41 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_encoder *encoder; int pipe = intel_crtc->pipe; + int plane = intel_crtc->plane; bool is_dsi; + u32 dspcntr; WARN_ON(!crtc->enabled); if (intel_crtc->active) return; + vlv_prepare_pll(intel_crtc); + + /* Set up the display plane register */ + dspcntr = DISPPLANE_GAMMA_ENABLE; + + if (intel_crtc->config.has_dp_encoder) + intel_dp_set_m_n(intel_crtc); + + intel_set_pipe_timings(intel_crtc); + + /* pipesrc and dspsize control the size that is scaled from, + * which should always be the user's requested size. + */ + I915_WRITE(DSPSIZE(plane), + ((intel_crtc->config.pipe_src_h - 1) << 16) | + (intel_crtc->config.pipe_src_w - 1)); + I915_WRITE(DSPPOS(plane), 0); + + i9xx_set_pipeconf(intel_crtc); + + I915_WRITE(DSPCNTR(plane), dspcntr); + POSTING_READ(DSPCNTR(plane)); + + dev_priv->display.update_primary_plane(crtc, crtc->primary->fb, + crtc->x, crtc->y); + intel_crtc->active = true; for_each_encoder_on_crtc(dev, crtc, encoder) @@ -4536,13 +4625,21 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc) intel_update_watermarks(crtc); intel_enable_pipe(intel_crtc); - intel_wait_for_vblank(dev_priv->dev, pipe); intel_set_cpu_fifo_underrun_reporting(dev, pipe, true); - intel_crtc_enable_planes(crtc); - for_each_encoder_on_crtc(dev, crtc, encoder) encoder->enable(encoder); + + intel_crtc_enable_planes(crtc); +} + +static void i9xx_set_pll_dividers(struct intel_crtc *crtc) +{ + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + + I915_WRITE(FP0(crtc->pipe), crtc->config.dpll_hw_state.fp0); + I915_WRITE(FP1(crtc->pipe), crtc->config.dpll_hw_state.fp1); } static void i9xx_crtc_enable(struct drm_crtc *crtc) @@ -4552,12 +4649,45 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_encoder *encoder; int pipe = intel_crtc->pipe; + int plane = intel_crtc->plane; + u32 dspcntr; WARN_ON(!crtc->enabled); if (intel_crtc->active) return; + i9xx_set_pll_dividers(intel_crtc); + + /* Set up the display plane register */ + dspcntr = DISPPLANE_GAMMA_ENABLE; + + if (pipe == 0) + dspcntr &= ~DISPPLANE_SEL_PIPE_MASK; + else + dspcntr |= DISPPLANE_SEL_PIPE_B; + + if (intel_crtc->config.has_dp_encoder) + intel_dp_set_m_n(intel_crtc); + + intel_set_pipe_timings(intel_crtc); + + /* pipesrc and dspsize control the size that is scaled from, + * which should always be the user's requested size. + */ + I915_WRITE(DSPSIZE(plane), + ((intel_crtc->config.pipe_src_h - 1) << 16) | + (intel_crtc->config.pipe_src_w - 1)); + I915_WRITE(DSPPOS(plane), 0); + + i9xx_set_pipeconf(intel_crtc); + + I915_WRITE(DSPCNTR(plane), dspcntr); + POSTING_READ(DSPCNTR(plane)); + + dev_priv->display.update_primary_plane(crtc, crtc->primary->fb, + crtc->x, crtc->y); + intel_crtc->active = true; for_each_encoder_on_crtc(dev, crtc, encoder) @@ -4572,13 +4702,12 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) intel_update_watermarks(crtc); intel_enable_pipe(intel_crtc); - intel_wait_for_vblank(dev_priv->dev, pipe); intel_set_cpu_fifo_underrun_reporting(dev, pipe, true); - intel_crtc_enable_planes(crtc); - for_each_encoder_on_crtc(dev, crtc, encoder) encoder->enable(encoder); + + intel_crtc_enable_planes(crtc); } static void i9xx_pfit_disable(struct intel_crtc *crtc) @@ -4607,11 +4736,11 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) if (!intel_crtc->active) return; + intel_crtc_disable_planes(crtc); + for_each_encoder_on_crtc(dev, crtc, encoder) encoder->disable(encoder); - intel_crtc_disable_planes(crtc); - intel_set_cpu_fifo_underrun_reporting(dev, pipe, false); intel_disable_pipe(dev_priv, pipe); @@ -4633,7 +4762,10 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) intel_crtc->active = false; intel_update_watermarks(crtc); + mutex_lock(&dev->struct_mutex); intel_update_fbc(dev); + intel_edp_psr_update(dev); + mutex_unlock(&dev->struct_mutex); } static void i9xx_crtc_off(struct drm_crtc *crtc) @@ -4696,13 +4828,11 @@ 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 intel_crtc *intel_crtc = to_intel_crtc(crtc); /* crtc should still be enabled when we disable it. */ WARN_ON(!crtc->enabled); dev_priv->display.crtc_disable(crtc); - intel_crtc->eld_vld = false; intel_crtc_update_sarea(crtc, false); dev_priv->display.off(crtc); @@ -5170,8 +5300,6 @@ static void i9xx_update_pll_dividers(struct intel_crtc *crtc, intel_clock_t *reduced_clock) { struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - int pipe = crtc->pipe; u32 fp, fp2 = 0; if (IS_PINEVIEW(dev)) { @@ -5184,17 +5312,14 @@ static void i9xx_update_pll_dividers(struct intel_crtc *crtc, fp2 = i9xx_dpll_compute_fp(reduced_clock); } - I915_WRITE(FP0(pipe), fp); crtc->config.dpll_hw_state.fp0 = fp; crtc->lowfreq_avail = false; if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS) && reduced_clock && i915.powersave) { - I915_WRITE(FP1(pipe), fp2); crtc->config.dpll_hw_state.fp1 = fp2; crtc->lowfreq_avail = true; } else { - I915_WRITE(FP1(pipe), fp); crtc->config.dpll_hw_state.fp1 = fp; } } @@ -5271,13 +5396,35 @@ static void intel_dp_set_m_n(struct intel_crtc *crtc) } static void vlv_update_pll(struct intel_crtc *crtc) +{ + u32 dpll, dpll_md; + + /* + * Enable DPIO clock input. We should never disable the reference + * clock for pipe B, since VGA hotplug / manual detection depends + * on it. + */ + dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REFA_CLK_ENABLE_VLV | + DPLL_VGA_MODE_DIS | DPLL_INTEGRATED_CLOCK_VLV; + /* We should never disable this, set it here for state tracking */ + if (crtc->pipe == PIPE_B) + dpll |= DPLL_INTEGRATED_CRI_CLK_VLV; + dpll |= DPLL_VCO_ENABLE; + crtc->config.dpll_hw_state.dpll = dpll; + + dpll_md = (crtc->config.pixel_multiplier - 1) + << DPLL_MD_UDI_MULTIPLIER_SHIFT; + crtc->config.dpll_hw_state.dpll_md = dpll_md; +} + +static void vlv_prepare_pll(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; int pipe = crtc->pipe; - u32 dpll, mdiv; + u32 mdiv; u32 bestn, bestm1, bestm2, bestp1, bestp2; - u32 coreclk, reg_val, dpll_md; + u32 coreclk, reg_val; mutex_lock(&dev_priv->dpio_lock); @@ -5290,7 +5437,7 @@ static void vlv_update_pll(struct intel_crtc *crtc) /* See eDP HDMI DPIO driver vbios notes doc */ /* PLL B needs special handling */ - if (pipe) + if (pipe == PIPE_B) vlv_pllb_recal_opamp(dev_priv, pipe); /* Set up Tx target for periodic Rcomp update */ @@ -5334,7 +5481,7 @@ static void vlv_update_pll(struct intel_crtc *crtc) if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP) || intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT)) { /* Use SSC source */ - if (!pipe) + if (pipe == PIPE_A) vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe), 0x0df40000); else @@ -5342,7 +5489,7 @@ static void vlv_update_pll(struct intel_crtc *crtc) 0x0df70000); } else { /* HDMI or VGA */ /* Use bend source */ - if (!pipe) + if (pipe == PIPE_A) vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe), 0x0df70000); else @@ -5358,24 +5505,6 @@ static void vlv_update_pll(struct intel_crtc *crtc) vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW7(pipe), coreclk); vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW11(pipe), 0x87871000); - - /* - * Enable DPIO clock input. We should never disable the reference - * clock for pipe B, since VGA hotplug / manual detection depends - * on it. - */ - dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REFA_CLK_ENABLE_VLV | - DPLL_VGA_MODE_DIS | DPLL_INTEGRATED_CLOCK_VLV; - /* We should never disable this, set it here for state tracking */ - if (pipe == PIPE_B) - dpll |= DPLL_INTEGRATED_CRI_CLK_VLV; - dpll |= DPLL_VCO_ENABLE; - crtc->config.dpll_hw_state.dpll = dpll; - - dpll_md = (crtc->config.pixel_multiplier - 1) - << DPLL_MD_UDI_MULTIPLIER_SHIFT; - crtc->config.dpll_hw_state.dpll_md = dpll_md; - mutex_unlock(&dev_priv->dpio_lock); } @@ -5386,11 +5515,18 @@ static void chv_update_pll(struct intel_crtc *crtc) int pipe = crtc->pipe; int dpll_reg = DPLL(crtc->pipe); enum dpio_channel port = vlv_pipe_to_channel(pipe); - u32 val, loopfilter, intcoeff; + u32 loopfilter, intcoeff; u32 bestn, bestm1, bestm2, bestp1, bestp2, bestm2_frac; int refclk; - mutex_lock(&dev_priv->dpio_lock); + crtc->config.dpll_hw_state.dpll = DPLL_SSC_REF_CLOCK_CHV | + DPLL_REFA_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS | + DPLL_VCO_ENABLE; + if (pipe != PIPE_A) + crtc->config.dpll_hw_state.dpll |= DPLL_INTEGRATED_CRI_CLK_VLV; + + crtc->config.dpll_hw_state.dpll_md = + (crtc->config.pixel_multiplier - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT; bestn = crtc->config.dpll.n; bestm2_frac = crtc->config.dpll.m2 & 0x3fffff; @@ -5402,19 +5538,10 @@ static void chv_update_pll(struct intel_crtc *crtc) /* * Enable Refclk and SSC */ - val = I915_READ(dpll_reg); - val |= (DPLL_SSC_REF_CLOCK_CHV | DPLL_REFA_CLK_ENABLE_VLV); - I915_WRITE(dpll_reg, val); - - /* Propagate soft reset to data lane reset */ - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS_DW0(port)); - val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); - vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port), val); + I915_WRITE(dpll_reg, + crtc->config.dpll_hw_state.dpll & ~DPLL_VCO_ENABLE); - /* Disable 10bit clock to display controller */ - val = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW14(port)); - val &= ~DPIO_DCLKP_EN; - vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW14(port), val); + mutex_lock(&dev_priv->dpio_lock); /* p1 and p2 divider */ vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW13(port), @@ -5773,16 +5900,12 @@ static int i9xx_crtc_mode_set(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); - int pipe = intel_crtc->pipe; - int plane = intel_crtc->plane; int refclk, num_connectors = 0; intel_clock_t clock, reduced_clock; - u32 dspcntr; bool ok, has_reduced_clock = false; bool is_lvds = false, is_dsi = false; struct intel_encoder *encoder; const intel_limit_t *limit; - int ret; for_each_encoder_on_crtc(dev, crtc, encoder) { switch (encoder->type) { @@ -5798,7 +5921,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, } if (is_dsi) - goto skip_dpll; + return 0; if (!intel_crtc->config.clock_set) { refclk = i9xx_get_refclk(crtc, num_connectors); @@ -5850,41 +5973,10 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, } else { i9xx_update_pll(intel_crtc, has_reduced_clock ? &reduced_clock : NULL, - num_connectors); - } - -skip_dpll: - /* Set up the display plane register */ - dspcntr = DISPPLANE_GAMMA_ENABLE; - - if (!IS_VALLEYVIEW(dev)) { - if (pipe == 0) - dspcntr &= ~DISPPLANE_SEL_PIPE_MASK; - else - dspcntr |= DISPPLANE_SEL_PIPE_B; + num_connectors); } - if (intel_crtc->config.has_dp_encoder) - intel_dp_set_m_n(intel_crtc); - - intel_set_pipe_timings(intel_crtc); - - /* pipesrc and dspsize control the size that is scaled from, - * which should always be the user's requested size. - */ - I915_WRITE(DSPSIZE(plane), - ((intel_crtc->config.pipe_src_h - 1) << 16) | - (intel_crtc->config.pipe_src_w - 1)); - I915_WRITE(DSPPOS(plane), 0); - - i9xx_set_pipeconf(intel_crtc); - - I915_WRITE(DSPCNTR(plane), dspcntr); - POSTING_READ(DSPCNTR(plane)); - - ret = intel_pipe_set_base(crtc, x, y, fb); - - return ret; + return 0; } static void i9xx_get_pfit_config(struct intel_crtc *crtc, @@ -6068,6 +6160,9 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, } } + if (IS_VALLEYVIEW(dev) && (tmp & PIPECONF_COLOR_RANGE_SELECT)) + pipe_config->limited_color_range = true; + if (INTEL_INFO(dev)->gen < 4) pipe_config->double_wide = tmp & PIPECONF_DOUBLE_WIDE; @@ -6226,8 +6321,7 @@ static void ironlake_init_pch_refclk(struct drm_device *dev) if (intel_panel_use_ssc(dev_priv) && can_ssc) { DRM_DEBUG_KMS("Using SSC on eDP\n"); val |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; - } - else + } else val |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD; } else val |= DREF_CPU_SOURCE_OUTPUT_DISABLE; @@ -6806,10 +6900,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, struct drm_framebuffer *fb) { struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - int pipe = intel_crtc->pipe; - int plane = intel_crtc->plane; int num_connectors = 0; intel_clock_t clock, reduced_clock; u32 dpll = 0, fp = 0, fp2 = 0; @@ -6817,7 +6908,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, bool is_lvds = false; struct intel_encoder *encoder; struct intel_shared_dpll *pll; - int ret; for_each_encoder_on_crtc(dev, crtc, encoder) { switch (encoder->type) { @@ -6867,36 +6957,18 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, pll = intel_get_shared_dpll(intel_crtc); if (pll == NULL) { DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n", - pipe_name(pipe)); + pipe_name(intel_crtc->pipe)); return -EINVAL; } } else intel_put_shared_dpll(intel_crtc); - if (intel_crtc->config.has_dp_encoder) - intel_dp_set_m_n(intel_crtc); - if (is_lvds && has_reduced_clock && i915.powersave) intel_crtc->lowfreq_avail = true; else intel_crtc->lowfreq_avail = false; - intel_set_pipe_timings(intel_crtc); - - if (intel_crtc->config.has_pch_encoder) { - intel_cpu_transcoder_set_m_n(intel_crtc, - &intel_crtc->config.fdi_m_n); - } - - ironlake_set_pipeconf(crtc); - - /* Set up the display plane register */ - I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE); - POSTING_READ(DSPCNTR(plane)); - - ret = intel_pipe_set_base(crtc, x, y, fb); - - return ret; + return 0; } static void intel_pch_transcoder_get_m_n(struct intel_crtc *crtc, @@ -7074,6 +7146,9 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc, break; } + if (tmp & PIPECONF_COLOR_RANGE_SELECT) + pipe_config->limited_color_range = true; + if (I915_READ(PCH_TRANSCONF(crtc->pipe)) & TRANS_ENABLE) { struct intel_shared_dpll *pll; @@ -7124,7 +7199,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv) struct intel_ddi_plls *plls = &dev_priv->ddi_plls; struct intel_crtc *crtc; - list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) + for_each_intel_crtc(dev, crtc) WARN(crtc->active, "CRTC for pipe %c enabled\n", pipe_name(crtc->pipe)); @@ -7359,39 +7434,15 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *fb) { - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - int plane = intel_crtc->plane; - int ret; if (!intel_ddi_pll_select(intel_crtc)) return -EINVAL; intel_ddi_pll_enable(intel_crtc); - if (intel_crtc->config.has_dp_encoder) - intel_dp_set_m_n(intel_crtc); - intel_crtc->lowfreq_avail = false; - intel_set_pipe_timings(intel_crtc); - - if (intel_crtc->config.has_pch_encoder) { - intel_cpu_transcoder_set_m_n(intel_crtc, - &intel_crtc->config.fdi_m_n); - } - - haswell_set_pipeconf(crtc); - - intel_set_pipe_csc(crtc); - - /* Set up the display plane register */ - I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE | DISPPLANE_PIPE_CSC_ENABLE); - POSTING_READ(DSPCNTR(plane)); - - ret = intel_pipe_set_base(crtc, x, y, fb); - - return ret; + return 0; } static bool haswell_get_pipe_config(struct intel_crtc *crtc, @@ -7471,40 +7522,6 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, return true; } -static int intel_crtc_mode_set(struct drm_crtc *crtc, - int x, int y, - struct drm_framebuffer *fb) -{ - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_encoder *encoder; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct drm_display_mode *mode = &intel_crtc->config.requested_mode; - int pipe = intel_crtc->pipe; - int ret; - - drm_vblank_pre_modeset(dev, pipe); - - ret = dev_priv->display.crtc_mode_set(crtc, x, y, fb); - - drm_vblank_post_modeset(dev, pipe); - - if (ret != 0) - return ret; - - for_each_encoder_on_crtc(dev, crtc, encoder) { - DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n", - encoder->base.base.id, - drm_get_encoder_name(&encoder->base), - mode->base.id, mode->name); - - if (encoder->mode_set) - encoder->mode_set(encoder); - } - - return 0; -} - static struct { int clock; u32 config; @@ -7619,7 +7636,6 @@ static void haswell_write_eld(struct drm_connector *connector, { struct drm_i915_private *dev_priv = connector->dev->dev_private; uint8_t *eld = connector->eld; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); uint32_t eldv; uint32_t i; int len; @@ -7658,7 +7674,6 @@ static void haswell_write_eld(struct drm_connector *connector, DRM_DEBUG_DRIVER("ELD on pipe %c\n", pipe_name(pipe)); eldv = AUDIO_ELD_VALID_A << (pipe * 4); - intel_crtc->eld_vld = true; if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n"); @@ -7899,7 +7914,7 @@ static void ivb_update_cursor(struct drm_crtc *crtc, u32 base) if (intel_crtc->cursor_visible != visible) { int16_t width = intel_crtc->cursor_width; - uint32_t cntl = I915_READ(CURCNTR_IVB(pipe)); + uint32_t cntl = I915_READ(CURCNTR(pipe)); if (base) { cntl &= ~CURSOR_MODE; cntl |= MCURSOR_GAMMA_ENABLE; @@ -7925,14 +7940,14 @@ static void ivb_update_cursor(struct drm_crtc *crtc, u32 base) cntl |= CURSOR_PIPE_CSC_ENABLE; cntl &= ~CURSOR_TRICKLE_FEED_DISABLE; } - I915_WRITE(CURCNTR_IVB(pipe), cntl); + I915_WRITE(CURCNTR(pipe), cntl); intel_crtc->cursor_visible = visible; } /* and commit changes on next vblank */ - POSTING_READ(CURCNTR_IVB(pipe)); - I915_WRITE(CURBASE_IVB(pipe), base); - POSTING_READ(CURBASE_IVB(pipe)); + POSTING_READ(CURCNTR(pipe)); + I915_WRITE(CURBASE(pipe), base); + POSTING_READ(CURBASE(pipe)); } /* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */ @@ -7979,16 +7994,14 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc, if (!visible && !intel_crtc->cursor_visible) return; - if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev) || IS_BROADWELL(dev)) { - I915_WRITE(CURPOS_IVB(pipe), pos); + I915_WRITE(CURPOS(pipe), pos); + + if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev) || IS_BROADWELL(dev)) ivb_update_cursor(crtc, base); - } else { - I915_WRITE(CURPOS(pipe), pos); - if (IS_845G(dev) || IS_I865G(dev)) - i845_update_cursor(crtc, base); - else - i9xx_update_cursor(crtc, base); - } + else if (IS_845G(dev) || IS_I865G(dev)) + i845_update_cursor(crtc, base); + else + i9xx_update_cursor(crtc, base); } static int intel_crtc_cursor_set(struct drm_crtc *crtc, @@ -8304,7 +8317,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector, } /* Find an unused one (if possible) */ - list_for_each_entry(possible_crtc, &dev->mode_config.crtc_list, head) { + for_each_crtc(dev, possible_crtc) { i++; if (!(encoder->possible_crtcs & (1 << i))) continue; @@ -8695,7 +8708,7 @@ void intel_mark_idle(struct drm_device *dev) if (!i915.powersave) goto out; - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + for_each_crtc(dev, crtc) { if (!crtc->primary->fb) continue; @@ -8718,7 +8731,7 @@ void intel_mark_fb_busy(struct drm_i915_gem_object *obj, if (!i915.powersave) return; - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + for_each_crtc(dev, crtc) { if (!crtc->primary->fb) continue; @@ -8833,6 +8846,48 @@ void intel_finish_page_flip_plane(struct drm_device *dev, int plane) do_intel_finish_page_flip(dev, crtc); } +/* Is 'a' after or equal to 'b'? */ +static bool g4x_flip_count_after_eq(u32 a, u32 b) +{ + return !((a - b) & 0x80000000); +} + +static bool page_flip_finished(struct intel_crtc *crtc) +{ + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + + /* + * The relevant registers doen't exist on pre-ctg. + * As the flip done interrupt doesn't trigger for mmio + * flips on gmch platforms, a flip count check isn't + * really needed there. But since ctg has the registers, + * include it in the check anyway. + */ + if (INTEL_INFO(dev)->gen < 5 && !IS_G4X(dev)) + return true; + + /* + * A DSPSURFLIVE check isn't enough in case the mmio and CS flips + * used the same base address. In that case the mmio flip might + * have completed, but the CS hasn't even executed the flip yet. + * + * A flip count check isn't enough as the CS might have updated + * the base address just after start of vblank, but before we + * managed to process the interrupt. This means we'd complete the + * CS flip too soon. + * + * Combining both checks should get us a good enough result. It may + * still happen that the CS flip has been executed, but has not + * yet actually completed. But in case the base address is the same + * anyway, we don't really care. + */ + return (I915_READ(DSPSURFLIVE(crtc->plane)) & ~0xfff) == + crtc->unpin_work->gtt_offset && + g4x_flip_count_after_eq(I915_READ(PIPE_FLIPCOUNT_GM45(crtc->pipe)), + crtc->unpin_work->flip_count); +} + void intel_prepare_page_flip(struct drm_device *dev, int plane) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -8845,12 +8900,12 @@ void intel_prepare_page_flip(struct drm_device *dev, int plane) * is also accompanied by a spurious intel_prepare_page_flip(). */ spin_lock_irqsave(&dev->event_lock, flags); - if (intel_crtc->unpin_work) + if (intel_crtc->unpin_work && page_flip_finished(intel_crtc)) atomic_inc_not_zero(&intel_crtc->unpin_work->pending); spin_unlock_irqrestore(&dev->event_lock, flags); } -inline static void intel_mark_page_flip_active(struct intel_crtc *intel_crtc) +static inline void intel_mark_page_flip_active(struct intel_crtc *intel_crtc) { /* Ensure that the work item is consistent when activating it ... */ smp_wmb(); @@ -8875,6 +8930,9 @@ static int intel_gen2_queue_flip(struct drm_device *dev, if (ret) goto err; + intel_crtc->unpin_work->gtt_offset = + i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset; + ret = intel_ring_begin(ring, 6); if (ret) goto err_unpin; @@ -8891,7 +8949,7 @@ static int intel_gen2_queue_flip(struct drm_device *dev, 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, i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset); + intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset); intel_ring_emit(ring, 0); /* aux display base address, unused */ intel_mark_page_flip_active(intel_crtc); @@ -8920,6 +8978,9 @@ static int intel_gen3_queue_flip(struct drm_device *dev, if (ret) goto err; + intel_crtc->unpin_work->gtt_offset = + i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset; + ret = intel_ring_begin(ring, 6); if (ret) goto err_unpin; @@ -8933,7 +8994,7 @@ static int intel_gen3_queue_flip(struct drm_device *dev, 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, i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset); + intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset); intel_ring_emit(ring, MI_NOOP); intel_mark_page_flip_active(intel_crtc); @@ -8962,6 +9023,9 @@ static int intel_gen4_queue_flip(struct drm_device *dev, if (ret) goto err; + intel_crtc->unpin_work->gtt_offset = + i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset; + ret = intel_ring_begin(ring, 4); if (ret) goto err_unpin; @@ -8973,8 +9037,7 @@ static int intel_gen4_queue_flip(struct drm_device *dev, 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, - (i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset) | + intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset | obj->tiling_mode); /* XXX Enabling the panel-fitter across page-flip is so far @@ -9011,6 +9074,9 @@ static int intel_gen6_queue_flip(struct drm_device *dev, if (ret) goto err; + intel_crtc->unpin_work->gtt_offset = + i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset; + ret = intel_ring_begin(ring, 4); if (ret) goto err_unpin; @@ -9018,7 +9084,7 @@ static int intel_gen6_queue_flip(struct drm_device *dev, 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, i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset); + intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset); /* Contrary to the suggestions in the documentation, * "Enable Panel Fitter" does not seem to be required when page @@ -9060,7 +9126,10 @@ static int intel_gen7_queue_flip(struct drm_device *dev, if (ret) goto err; - switch(intel_crtc->plane) { + intel_crtc->unpin_work->gtt_offset = + i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset; + + switch (intel_crtc->plane) { case PLANE_A: plane_bit = MI_DISPLAY_FLIP_IVB_PLANE_A; break; @@ -9137,7 +9206,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev, intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit); intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode)); - intel_ring_emit(ring, i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset); + intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset); intel_ring_emit(ring, (MI_NOOP)); intel_mark_page_flip_active(intel_crtc); @@ -9235,6 +9304,9 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, atomic_inc(&intel_crtc->unpin_work_count); intel_crtc->reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter); + if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev)) + work->flip_count = I915_READ(PIPE_FLIPCOUNT_GM45(intel_crtc->pipe)) + 1; + ret = dev_priv->display.queue_flip(dev, crtc, fb, obj, page_flip_flags); if (ret) goto cleanup_pending; @@ -9302,8 +9374,7 @@ static void intel_modeset_update_staged_output_state(struct drm_device *dev) to_intel_crtc(encoder->base.crtc); } - list_for_each_entry(crtc, &dev->mode_config.crtc_list, - base.head) { + for_each_intel_crtc(dev, crtc) { crtc->new_enabled = crtc->base.enabled; if (crtc->new_enabled) @@ -9334,14 +9405,13 @@ static void intel_modeset_commit_output_state(struct drm_device *dev) encoder->base.crtc = &encoder->new_crtc->base; } - list_for_each_entry(crtc, &dev->mode_config.crtc_list, - base.head) { + for_each_intel_crtc(dev, crtc) { crtc->base.enabled = crtc->new_enabled; } } static void -connected_sink_compute_bpp(struct intel_connector * connector, +connected_sink_compute_bpp(struct intel_connector *connector, struct intel_crtc_config *pipe_config) { int bpp = pipe_config->pipe_bpp; @@ -9689,8 +9759,7 @@ intel_modeset_affected_pipes(struct drm_crtc *crtc, unsigned *modeset_pipes, } /* Check for pipes that will be enabled/disabled ... */ - list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, - base.head) { + for_each_intel_crtc(dev, intel_crtc) { if (intel_crtc->base.enabled == intel_crtc->new_enabled) continue; @@ -9763,8 +9832,7 @@ intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes) intel_modeset_commit_output_state(dev); /* Double check state. */ - list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, - base.head) { + for_each_intel_crtc(dev, intel_crtc) { WARN_ON(intel_crtc->base.enabled != intel_crtc_in_use(&intel_crtc->base)); WARN_ON(intel_crtc->new_config && intel_crtc->new_config != &intel_crtc->config); @@ -9893,6 +9961,12 @@ intel_pipe_config_compare(struct drm_device *dev, PIPE_CONF_CHECK_I(adjusted_mode.crtc_vsync_end); PIPE_CONF_CHECK_I(pixel_multiplier); + PIPE_CONF_CHECK_I(has_hdmi_sink); + if ((INTEL_INFO(dev)->gen < 8 && !IS_HASWELL(dev)) || + IS_VALLEYVIEW(dev)) + PIPE_CONF_CHECK_I(limited_color_range); + + PIPE_CONF_CHECK_I(has_audio); PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags, DRM_MODE_FLAG_INTERLACE); @@ -10042,8 +10116,7 @@ check_crtc_state(struct drm_device *dev) struct intel_encoder *encoder; struct intel_crtc_config pipe_config; - list_for_each_entry(crtc, &dev->mode_config.crtc_list, - base.head) { + for_each_intel_crtc(dev, crtc) { bool enabled = false; bool active = false; @@ -10132,8 +10205,7 @@ check_shared_dpll_state(struct drm_device *dev) "pll on state mismatch (expected %i, found %i)\n", pll->on, active); - list_for_each_entry(crtc, &dev->mode_config.crtc_list, - base.head) { + for_each_intel_crtc(dev, crtc) { if (crtc->base.enabled && intel_crtc_to_shared_dpll(crtc) == pll) enabled_crtcs++; if (crtc->active && intel_crtc_to_shared_dpll(crtc) == pll) @@ -10264,8 +10336,28 @@ static int __intel_set_mode(struct drm_crtc *crtc, * on the DPLL. */ for_each_intel_crtc_masked(dev, modeset_pipes, intel_crtc) { - ret = intel_crtc_mode_set(&intel_crtc->base, - x, y, fb); + struct drm_framebuffer *old_fb; + + mutex_lock(&dev->struct_mutex); + ret = intel_pin_and_fence_fb_obj(dev, + to_intel_framebuffer(fb)->obj, + NULL); + if (ret != 0) { + DRM_ERROR("pin & fence failed\n"); + mutex_unlock(&dev->struct_mutex); + goto done; + } + old_fb = crtc->primary->fb; + if (old_fb) + intel_unpin_fb_obj(to_intel_framebuffer(old_fb)->obj); + mutex_unlock(&dev->struct_mutex); + + crtc->primary->fb = fb; + crtc->x = x; + crtc->y = y; + + ret = dev_priv->display.crtc_mode_set(&intel_crtc->base, + x, y, fb); if (ret) goto done; } @@ -10348,7 +10440,7 @@ static int intel_set_config_save_state(struct drm_device *dev, * restored, not the drivers personal bookkeeping. */ count = 0; - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + for_each_crtc(dev, crtc) { config->save_crtc_enabled[count++] = crtc->enabled; } @@ -10374,7 +10466,7 @@ static void intel_set_config_restore_state(struct drm_device *dev, int count; count = 0; - list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) { + for_each_intel_crtc(dev, crtc) { crtc->new_enabled = config->save_crtc_enabled[count++]; if (crtc->new_enabled) @@ -10564,8 +10656,7 @@ intel_modeset_stage_output_state(struct drm_device *dev, } /* Now we've also updated encoder->new_crtc for all encoders. */ - list_for_each_entry(crtc, &dev->mode_config.crtc_list, - base.head) { + for_each_intel_crtc(dev, crtc) { crtc->new_enabled = false; list_for_each_entry(encoder, @@ -10778,7 +10869,7 @@ static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv, struct intel_crtc *crtc; /* Make sure no transcoder isn't still depending on us. */ - list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) { + for_each_intel_crtc(dev, crtc) { if (intel_crtc_to_shared_dpll(crtc) == pll) assert_pch_transcoder_disabled(dev_priv, crtc->pipe); } @@ -11027,6 +11118,15 @@ static void intel_setup_outputs(struct drm_device *dev) intel_dp_init(dev, VLV_DISPLAY_BASE + DP_C, PORT_C); } + if (IS_CHERRYVIEW(dev)) { + if (I915_READ(VLV_DISPLAY_BASE + CHV_HDMID) & SDVO_DETECTED) { + intel_hdmi_init(dev, VLV_DISPLAY_BASE + CHV_HDMID, + PORT_D); + if (I915_READ(VLV_DISPLAY_BASE + DP_D) & DP_DETECTED) + intel_dp_init(dev, VLV_DISPLAY_BASE + DP_D, PORT_D); + } + } + intel_dsi_init(dev); } else if (SUPPORTS_DIGITAL_OUTPUTS(dev)) { bool found = false; @@ -11631,8 +11731,7 @@ void intel_modeset_init(struct drm_device *dev) intel_modeset_setup_hw_state(dev, false); mutex_unlock(&dev->mode_config.mutex); - list_for_each_entry(crtc, &dev->mode_config.crtc_list, - base.head) { + for_each_intel_crtc(dev, crtc) { if (!crtc->active) continue; @@ -11893,8 +11992,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) struct intel_connector *connector; int i; - list_for_each_entry(crtc, &dev->mode_config.crtc_list, - base.head) { + for_each_intel_crtc(dev, crtc) { memset(&crtc->config, 0, sizeof(crtc->config)); crtc->config.quirks |= PIPE_CONFIG_QUIRK_INHERITED_MODE; @@ -11919,8 +12017,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) pll->on = pll->get_hw_state(dev_priv, pll, &pll->hw_state); pll->active = 0; - list_for_each_entry(crtc, &dev->mode_config.crtc_list, - base.head) { + for_each_intel_crtc(dev, crtc) { if (crtc->active && intel_crtc_to_shared_dpll(crtc) == pll) pll->active++; } @@ -11985,8 +12082,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev, * Note that this could go away if we move to using crtc_config * checking everywhere. */ - list_for_each_entry(crtc, &dev->mode_config.crtc_list, - base.head) { + for_each_intel_crtc(dev, crtc) { if (crtc->active && i915.fastboot) { intel_mode_from_pipe_config(&crtc->base.mode, &crtc->config); DRM_DEBUG_KMS("[CRTC:%d] found active mode: ", @@ -12062,7 +12158,7 @@ void intel_modeset_gem_init(struct drm_device *dev) * for this. */ mutex_lock(&dev->struct_mutex); - list_for_each_entry(c, &dev->mode_config.crtc_list, head) { + for_each_crtc(dev, c) { if (!c->primary->fb) continue; @@ -12108,7 +12204,7 @@ void intel_modeset_cleanup(struct drm_device *dev) intel_unregister_dsm_handler(); - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + for_each_crtc(dev, crtc) { /* Skip inactive CRTCs */ if (!crtc->primary->fb) continue; @@ -12264,15 +12360,9 @@ intel_display_capture_error_state(struct drm_device *dev) if (!error->pipe[i].power_domain_on) continue; - if (INTEL_INFO(dev)->gen <= 6 || IS_VALLEYVIEW(dev)) { - error->cursor[i].control = I915_READ(CURCNTR(i)); - error->cursor[i].position = I915_READ(CURPOS(i)); - error->cursor[i].base = I915_READ(CURBASE(i)); - } else { - error->cursor[i].control = I915_READ(CURCNTR_IVB(i)); - error->cursor[i].position = I915_READ(CURPOS_IVB(i)); - error->cursor[i].base = I915_READ(CURBASE_IVB(i)); - } + error->cursor[i].control = I915_READ(CURCNTR(i)); + error->cursor[i].position = I915_READ(CURPOS(i)); + error->cursor[i].base = I915_READ(CURBASE(i)); error->plane[i].control = I915_READ(DSPCNTR(i)); error->plane[i].stride = I915_READ(DSPSTRIDE(i));