diff options
author | Dave Airlie <airlied@redhat.com> | 2014-12-03 08:25:59 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2014-12-03 08:25:59 +1000 |
commit | 26045b53c96f23b75a48544349c3d936e8402418 (patch) | |
tree | ce550e556d6135aa45a376f067855b8aaa1b26ad /drivers/gpu/drm/i915/intel_display.c | |
parent | 1a92b7a241dcf06a92d84219b4124dcf420ae315 (diff) | |
parent | 064ca1d250b14b785e662b0a13d8d20cb84574e1 (diff) |
Merge tag 'drm-intel-next-2014-11-21-fixed' of git://anongit.freedesktop.org/drm-intel into drm-next
drm-intel-next-2014-11-21:
- infoframe tracking (for fastboot) from Jesse
- start of the dri1/ums support removal
- vlv forcewake timeout fixes (Imre)
- bunch of patches to polish the rps code (Imre) and improve it on bdw (Tom
O'Rourke)
- on-demand pinning for execlist contexts
- vlv/chv backlight improvements (Ville)
- gen8+ render ctx w/a work from various people
- skl edp programming (Satheeshakrishna et al.)
- psr docbook (Rodrigo)
- piles of little fixes and improvements all over, as usual
* tag 'drm-intel-next-2014-11-21-fixed' of git://anongit.freedesktop.org/drm-intel: (117 commits)
drm/i915: Don't pin LRC in GGTT when dumping in debugfs
drm/i915: Update DRIVER_DATE to 20141121
drm/i915/g4x: fix g4x infoframe readout
drm/i915: Only call mod_timer() if not already pending
drm/i915: Don't rely upon encoder->type for infoframe hw state readout
drm/i915: remove the IRQs enabled WARN from intel_disable_gt_powersave
drm/i915: Use ggtt error obj capture helper for gen8 semaphores
drm/i915: vlv: increase timeout when setting idle GPU freq
drm/i915: vlv: fix cdclk setting during modeset while suspended
drm/i915: Dump hdmi pipe_config state
drm/i915: Gen9 shadowed registers
drm/i915/skl: Gen9 multi-engine forcewake
drm/i915: Read power well status before other registers for drpc info
drm/i915: Pin tiled objects for L-shaped configs
drm/i915: Update ring freq for full gpu freq range
drm/i915: change initial rps frequency for gen8
drm/i915: Keep min freq above floor on HSW/BDW
drm/i915: Use efficient frequency for HSW/BDW
drm/i915: Can i915_gem_init_ioctl
drm/i915: Sanitize ->lastclose
...
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 384 |
1 files changed, 301 insertions, 83 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e9a0df8a437..853697fc4d4 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2931,8 +2931,6 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, return ret; } - intel_update_pipe_size(intel_crtc); - dev_priv->display.update_primary_plane(crtc, fb, x, y); if (intel_crtc->active) @@ -4005,6 +4003,19 @@ static void cpt_verify_modeset(struct drm_device *dev, int pipe) } } +static void skylake_pfit_enable(struct intel_crtc *crtc) +{ + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + int pipe = crtc->pipe; + + if (crtc->config.pch_pfit.enabled) { + I915_WRITE(PS_CTL(pipe), PS_ENABLE); + I915_WRITE(PS_WIN_POS(pipe), crtc->config.pch_pfit.pos); + I915_WRITE(PS_WIN_SZ(pipe), crtc->config.pch_pfit.size); + } +} + static void ironlake_pfit_enable(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; @@ -4388,7 +4399,10 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) intel_ddi_enable_pipe_clock(intel_crtc); - ironlake_pfit_enable(intel_crtc); + if (IS_SKYLAKE(dev)) + skylake_pfit_enable(intel_crtc); + else + ironlake_pfit_enable(intel_crtc); /* * On ILK+ LUT must be loaded before the pipe is running but with @@ -4422,6 +4436,21 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) intel_crtc_enable_planes(crtc); } +static void skylake_pfit_disable(struct intel_crtc *crtc) +{ + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + int pipe = crtc->pipe; + + /* To avoid upsetting the power well on haswell only disable the pfit if + * it's in use. The hw state code will make sure we get this right. */ + if (crtc->config.pch_pfit.enabled) { + I915_WRITE(PS_CTL(pipe), 0); + I915_WRITE(PS_WIN_POS(pipe), 0); + I915_WRITE(PS_WIN_SZ(pipe), 0); + } +} + static void ironlake_pfit_disable(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; @@ -4534,7 +4563,10 @@ static void haswell_crtc_disable(struct drm_crtc *crtc) intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder); - ironlake_pfit_disable(intel_crtc); + if (IS_SKYLAKE(dev)) + skylake_pfit_disable(intel_crtc); + else + ironlake_pfit_disable(intel_crtc); intel_ddi_disable_pipe_clock(intel_crtc); @@ -4907,10 +4939,23 @@ static void valleyview_modeset_global_resources(struct drm_device *dev) int req_cdclk = valleyview_calc_cdclk(dev_priv, max_pixclk); if (req_cdclk != dev_priv->vlv_cdclk_freq) { + /* + * FIXME: We can end up here with all power domains off, yet + * with a CDCLK frequency other than the minimum. To account + * for this take the PIPE-A power domain, which covers the HW + * blocks needed for the following programming. This can be + * removed once it's guaranteed that we get here either with + * the minimum CDCLK set, or the required power domains + * enabled. + */ + intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A); + if (IS_CHERRYVIEW(dev)) cherryview_set_cdclk(dev, req_cdclk); else valleyview_set_cdclk(dev, req_cdclk); + + intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A); } } @@ -5153,36 +5198,6 @@ static void i9xx_crtc_off(struct drm_crtc *crtc) { } -static void intel_crtc_update_sarea(struct drm_crtc *crtc, - bool enabled) -{ - struct drm_device *dev = crtc->dev; - struct drm_i915_master_private *master_priv; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - int pipe = intel_crtc->pipe; - - if (!dev->primary->master) - return; - - master_priv = dev->primary->master->driver_priv; - if (!master_priv->sarea_priv) - return; - - switch (pipe) { - case 0: - master_priv->sarea_priv->pipeA_w = enabled ? crtc->mode.hdisplay : 0; - master_priv->sarea_priv->pipeA_h = enabled ? crtc->mode.vdisplay : 0; - break; - case 1: - master_priv->sarea_priv->pipeB_w = enabled ? crtc->mode.hdisplay : 0; - master_priv->sarea_priv->pipeB_h = enabled ? crtc->mode.vdisplay : 0; - break; - default: - DRM_ERROR("Can't update pipe %c in SAREA\n", pipe_name(pipe)); - break; - } -} - /* Master function to enable/disable CRTC and corresponding power wells */ void intel_crtc_control(struct drm_crtc *crtc, bool enable) { @@ -5226,8 +5241,6 @@ void intel_crtc_update_dpms(struct drm_crtc *crtc) enable |= intel_encoder->connectors_active; intel_crtc_control(crtc, enable); - - intel_crtc_update_sarea(crtc, enable); } static void intel_crtc_disable(struct drm_crtc *crtc) @@ -5242,7 +5255,6 @@ static void intel_crtc_disable(struct drm_crtc *crtc) WARN_ON(!crtc->enabled); dev_priv->display.crtc_disable(crtc); - intel_crtc_update_sarea(crtc, false); dev_priv->display.off(crtc); if (crtc->primary->fb) { @@ -7549,6 +7561,22 @@ static void ironlake_get_fdi_m_n_config(struct intel_crtc *crtc, &pipe_config->fdi_m_n, NULL); } +static void skylake_get_pfit_config(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; + uint32_t tmp; + + tmp = I915_READ(PS_CTL(crtc->pipe)); + + if (tmp & PS_ENABLE) { + pipe_config->pch_pfit.enabled = true; + pipe_config->pch_pfit.pos = I915_READ(PS_WIN_POS(crtc->pipe)); + pipe_config->pch_pfit.size = I915_READ(PS_WIN_SZ(crtc->pipe)); + } +} + static void ironlake_get_pfit_config(struct intel_crtc *crtc, struct intel_crtc_config *pipe_config) { @@ -7962,6 +7990,28 @@ static int haswell_crtc_compute_clock(struct intel_crtc *crtc) return 0; } +static void skylake_get_ddi_pll(struct drm_i915_private *dev_priv, + enum port port, + struct intel_crtc_config *pipe_config) +{ + u32 temp; + + temp = I915_READ(DPLL_CTRL2) & DPLL_CTRL2_DDI_CLK_SEL_MASK(port); + pipe_config->ddi_pll_sel = temp >> (port * 3 + 1); + + switch (pipe_config->ddi_pll_sel) { + case SKL_DPLL1: + pipe_config->shared_dpll = DPLL_ID_SKL_DPLL1; + break; + case SKL_DPLL2: + pipe_config->shared_dpll = DPLL_ID_SKL_DPLL2; + break; + case SKL_DPLL3: + pipe_config->shared_dpll = DPLL_ID_SKL_DPLL3; + break; + } +} + static void haswell_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, struct intel_crtc_config *pipe_config) @@ -7991,7 +8041,10 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc, port = (tmp & TRANS_DDI_PORT_MASK) >> TRANS_DDI_PORT_SHIFT; - haswell_get_ddi_pll(dev_priv, port, pipe_config); + if (IS_SKYLAKE(dev)) + skylake_get_ddi_pll(dev_priv, port, pipe_config); + else + haswell_get_ddi_pll(dev_priv, port, pipe_config); if (pipe_config->shared_dpll >= 0) { pll = &dev_priv->shared_dplls[pipe_config->shared_dpll]; @@ -8067,8 +8120,12 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, intel_get_pipe_timings(crtc, pipe_config); pfit_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe); - if (intel_display_power_is_enabled(dev_priv, pfit_domain)) - ironlake_get_pfit_config(crtc, pipe_config); + if (intel_display_power_is_enabled(dev_priv, pfit_domain)) { + if (IS_SKYLAKE(dev)) + skylake_get_pfit_config(crtc, pipe_config); + else + ironlake_get_pfit_config(crtc, pipe_config); + } if (IS_HASWELL(dev)) pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) && @@ -8292,7 +8349,7 @@ static int intel_crtc_cursor_set_obj(struct drm_crtc *crtc, uint32_t width, uint32_t height) { struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); enum pipe pipe = intel_crtc->pipe; unsigned old_width; @@ -8421,7 +8478,7 @@ __intel_framebuffer_create(struct drm_device *dev, intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); if (!intel_fb) { - drm_gem_object_unreference_unlocked(&obj->base); + drm_gem_object_unreference(&obj->base); return ERR_PTR(-ENOMEM); } @@ -8431,7 +8488,7 @@ __intel_framebuffer_create(struct drm_device *dev, return &intel_fb->base; err: - drm_gem_object_unreference_unlocked(&obj->base); + drm_gem_object_unreference(&obj->base); kfree(intel_fb); return ERR_PTR(ret); @@ -9465,6 +9522,69 @@ static int intel_queue_mmio_flip(struct drm_device *dev, return 0; } +static int intel_gen9_queue_flip(struct drm_device *dev, + struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_i915_gem_object *obj, + struct intel_engine_cs *ring, + uint32_t flags) +{ + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + uint32_t plane = 0, stride; + int ret; + + switch(intel_crtc->pipe) { + case PIPE_A: + plane = MI_DISPLAY_FLIP_SKL_PLANE_1_A; + break; + case PIPE_B: + plane = MI_DISPLAY_FLIP_SKL_PLANE_1_B; + break; + case PIPE_C: + plane = MI_DISPLAY_FLIP_SKL_PLANE_1_C; + break; + default: + WARN_ONCE(1, "unknown plane in flip command\n"); + return -ENODEV; + } + + switch (obj->tiling_mode) { + case I915_TILING_NONE: + stride = fb->pitches[0] >> 6; + break; + case I915_TILING_X: + stride = fb->pitches[0] >> 9; + break; + default: + WARN_ONCE(1, "unknown tiling in flip command\n"); + return -ENODEV; + } + + ret = intel_ring_begin(ring, 10); + if (ret) + return ret; + + intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); + intel_ring_emit(ring, DERRMR); + intel_ring_emit(ring, ~(DERRMR_PIPEA_PRI_FLIP_DONE | + DERRMR_PIPEB_PRI_FLIP_DONE | + DERRMR_PIPEC_PRI_FLIP_DONE)); + intel_ring_emit(ring, MI_STORE_REGISTER_MEM_GEN8(1) | + MI_SRM_LRM_GLOBAL_GTT); + intel_ring_emit(ring, DERRMR); + intel_ring_emit(ring, ring->scratch.gtt_offset + 256); + intel_ring_emit(ring, 0); + + intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane); + intel_ring_emit(ring, stride << 6 | obj->tiling_mode); + intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset); + + intel_mark_page_flip_active(intel_crtc); + __intel_ring_advance(ring); + + return 0; +} + static int intel_default_queue_flip(struct drm_device *dev, struct drm_crtc *crtc, struct drm_framebuffer *fb, @@ -9904,6 +10024,10 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, pipe_config->dp_m2_n2.link_n, pipe_config->dp_m2_n2.tu); + DRM_DEBUG_KMS("audio: %i, infoframes: %i\n", + pipe_config->has_audio, + pipe_config->has_infoframe); + DRM_DEBUG_KMS("requested mode:\n"); drm_mode_debug_printmodeline(&pipe_config->requested_mode); DRM_DEBUG_KMS("adjusted mode:\n"); @@ -10372,6 +10496,7 @@ intel_pipe_config_compare(struct drm_device *dev, if ((INTEL_INFO(dev)->gen < 8 && !IS_HASWELL(dev)) || IS_VALLEYVIEW(dev)) PIPE_CONF_CHECK_I(limited_color_range); + PIPE_CONF_CHECK_I(has_infoframe); PIPE_CONF_CHECK_I(has_audio); @@ -10428,6 +10553,9 @@ intel_pipe_config_compare(struct drm_device *dev, PIPE_CONF_CHECK_X(dpll_hw_state.fp0); PIPE_CONF_CHECK_X(dpll_hw_state.fp1); PIPE_CONF_CHECK_X(dpll_hw_state.wrpll); + PIPE_CONF_CHECK_X(dpll_hw_state.ctrl1); + PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr1); + PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr2); if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) PIPE_CONF_CHECK_I(pipe_bpp); @@ -10751,45 +10879,60 @@ static void update_scanline_offset(struct intel_crtc *crtc) crtc->scanline_offset = 1; } +static struct intel_crtc_config * +intel_modeset_compute_config(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_framebuffer *fb, + unsigned *modeset_pipes, + unsigned *prepare_pipes, + unsigned *disable_pipes) +{ + struct intel_crtc_config *pipe_config = NULL; + + intel_modeset_affected_pipes(crtc, modeset_pipes, + prepare_pipes, disable_pipes); + + if ((*modeset_pipes) == 0) + goto out; + + /* + * Note this needs changes when we start tracking multiple modes + * and crtcs. At that point we'll need to compute the whole config + * (i.e. one pipe_config for each crtc) rather than just the one + * for this crtc. + */ + pipe_config = intel_modeset_pipe_config(crtc, fb, mode); + if (IS_ERR(pipe_config)) { + goto out; + } + intel_dump_pipe_config(to_intel_crtc(crtc), pipe_config, + "[modeset]"); + to_intel_crtc(crtc)->new_config = pipe_config; + +out: + return pipe_config; +} + static int __intel_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, - int x, int y, struct drm_framebuffer *fb) + int x, int y, struct drm_framebuffer *fb, + struct intel_crtc_config *pipe_config, + unsigned modeset_pipes, + unsigned prepare_pipes, + unsigned disable_pipes) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_display_mode *saved_mode; - struct intel_crtc_config *pipe_config = NULL; struct intel_crtc *intel_crtc; - unsigned disable_pipes, prepare_pipes, modeset_pipes; int ret = 0; saved_mode = kmalloc(sizeof(*saved_mode), GFP_KERNEL); if (!saved_mode) return -ENOMEM; - intel_modeset_affected_pipes(crtc, &modeset_pipes, - &prepare_pipes, &disable_pipes); - *saved_mode = crtc->mode; - /* Hack: Because we don't (yet) support global modeset on multiple - * crtcs, we don't keep track of the new mode for more than one crtc. - * Hence simply check whether any bit is set in modeset_pipes in all the - * pieces of code that are not yet converted to deal with mutliple crtcs - * changing their mode at the same time. */ - if (modeset_pipes) { - pipe_config = intel_modeset_pipe_config(crtc, fb, mode); - if (IS_ERR(pipe_config)) { - ret = PTR_ERR(pipe_config); - pipe_config = NULL; - - goto out; - } - intel_dump_pipe_config(to_intel_crtc(crtc), pipe_config, - "[modeset]"); - to_intel_crtc(crtc)->new_config = pipe_config; - } - /* * See if the config requires any additional preparation, e.g. * to adjust global state with pipes off. We need to do this @@ -10830,6 +10973,10 @@ static int __intel_set_mode(struct drm_crtc *crtc, /* crtc->mode is already used by the ->mode_set callbacks, hence we need * to set it here already despite that we pass it down the callchain. + * + * Note we'll need to fix this up when we start tracking multiple + * pipes; here we assume a single modeset_pipe and only track the + * single crtc and mode. */ if (modeset_pipes) { crtc->mode = *mode; @@ -10891,19 +11038,23 @@ done: if (ret && crtc->enabled) crtc->mode = *saved_mode; -out: kfree(pipe_config); kfree(saved_mode); return ret; } -static int intel_set_mode(struct drm_crtc *crtc, - struct drm_display_mode *mode, - int x, int y, struct drm_framebuffer *fb) +static int intel_set_mode_pipes(struct drm_crtc *crtc, + struct drm_display_mode *mode, + int x, int y, struct drm_framebuffer *fb, + struct intel_crtc_config *pipe_config, + unsigned modeset_pipes, + unsigned prepare_pipes, + unsigned disable_pipes) { int ret; - ret = __intel_set_mode(crtc, mode, x, y, fb); + ret = __intel_set_mode(crtc, mode, x, y, fb, pipe_config, modeset_pipes, + prepare_pipes, disable_pipes); if (ret == 0) intel_modeset_check_state(crtc->dev); @@ -10911,6 +11062,26 @@ static int intel_set_mode(struct drm_crtc *crtc, return ret; } +static int intel_set_mode(struct drm_crtc *crtc, + struct drm_display_mode *mode, + int x, int y, struct drm_framebuffer *fb) +{ + struct intel_crtc_config *pipe_config; + unsigned modeset_pipes, prepare_pipes, disable_pipes; + + pipe_config = intel_modeset_compute_config(crtc, mode, fb, + &modeset_pipes, + &prepare_pipes, + &disable_pipes); + + if (IS_ERR(pipe_config)) + return PTR_ERR(pipe_config); + + return intel_set_mode_pipes(crtc, mode, x, y, fb, pipe_config, + modeset_pipes, prepare_pipes, + disable_pipes); +} + void intel_crtc_restore_mode(struct drm_crtc *crtc) { intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, crtc->primary->fb); @@ -11239,6 +11410,8 @@ static int intel_crtc_set_config(struct drm_mode_set *set) struct drm_device *dev; struct drm_mode_set save_set; struct intel_set_config *config; + struct intel_crtc_config *pipe_config; + unsigned modeset_pipes, prepare_pipes, disable_pipes; int ret; BUG_ON(!set); @@ -11284,9 +11457,36 @@ static int intel_crtc_set_config(struct drm_mode_set *set) if (ret) goto fail; + pipe_config = intel_modeset_compute_config(set->crtc, set->mode, + set->fb, + &modeset_pipes, + &prepare_pipes, + &disable_pipes); + if (IS_ERR(pipe_config)) { + ret = PTR_ERR(pipe_config); + goto fail; + } else if (pipe_config) { + if (to_intel_crtc(set->crtc)->new_config->has_audio != + to_intel_crtc(set->crtc)->config.has_audio) + config->mode_changed = true; + + /* Force mode sets for any infoframe stuff */ + if (to_intel_crtc(set->crtc)->new_config->has_infoframe || + to_intel_crtc(set->crtc)->config.has_infoframe) + config->mode_changed = true; + } + + /* set_mode will free it in the mode_changed case */ + if (!config->mode_changed) + kfree(pipe_config); + + intel_update_pipe_size(to_intel_crtc(set->crtc)); + if (config->mode_changed) { - ret = intel_set_mode(set->crtc, set->mode, - set->x, set->y, set->fb); + ret = intel_set_mode_pipes(set->crtc, set->mode, + set->x, set->y, set->fb, pipe_config, + modeset_pipes, prepare_pipes, + disable_pipes); } else if (config->fb_changed) { struct intel_crtc *intel_crtc = to_intel_crtc(set->crtc); @@ -11559,8 +11759,8 @@ intel_commit_primary_plane(struct drm_plane *plane, struct drm_rect *src = &state->src; crtc->primary->fb = fb; - crtc->x = src->x1; - crtc->y = src->y1; + crtc->x = src->x1 >> 16; + crtc->y = src->y1 >> 16; intel_plane->crtc_x = state->orig_dst.x1; intel_plane->crtc_y = state->orig_dst.y1; @@ -12009,7 +12209,7 @@ enum pipe intel_get_pipe_from_connector(struct intel_connector *connector) WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); - if (!encoder) + if (!encoder || WARN_ON(!encoder->crtc)) return INVALID_PIPE; return to_intel_crtc(encoder->crtc)->pipe; @@ -12244,7 +12444,7 @@ static void intel_setup_outputs(struct drm_device *dev) if (SUPPORTS_TV(dev)) intel_tv_init(dev); - intel_edp_psr_init(dev); + intel_psr_init(dev); for_each_intel_encoder(dev, encoder) { encoder->base.possible_crtcs = encoder->crtc_mask; @@ -12558,6 +12758,9 @@ static void intel_init_display(struct drm_device *dev) case 8: /* FIXME(BDW): Check that the gen8 RCS flip works. */ dev_priv->display.queue_flip = intel_gen7_queue_flip; break; + case 9: + dev_priv->display.queue_flip = intel_gen9_queue_flip; + break; } intel_panel_init_backlight_funcs(dev); @@ -13262,8 +13465,8 @@ void intel_modeset_setup_hw_state(struct drm_device *dev, struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; - __intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, - crtc->primary->fb); + intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, + crtc->primary->fb); } } else { intel_modeset_update_staged_output_state(dev); @@ -13274,6 +13477,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev, void intel_modeset_gem_init(struct drm_device *dev) { + struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc *c; struct drm_i915_gem_object *obj; @@ -13281,6 +13485,16 @@ void intel_modeset_gem_init(struct drm_device *dev) intel_init_gt_powersave(dev); mutex_unlock(&dev->struct_mutex); + /* + * There may be no VBT; and if the BIOS enabled SSC we can + * just keep using it to avoid unnecessary flicker. Whereas if the + * BIOS isn't using it, don't assume it will work even if the VBT + * indicates as much. + */ + if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) + dev_priv->vbt.lvds_use_ssc = !!(I915_READ(PCH_DREF_CONTROL) & + DREF_SSC1_ENABLE); + intel_modeset_init_hw(dev); intel_setup_overlay(dev); @@ -13306,6 +13520,8 @@ void intel_modeset_gem_init(struct drm_device *dev) } } mutex_unlock(&dev->struct_mutex); + + intel_backlight_register(dev); } void intel_connector_unregister(struct intel_connector *intel_connector) @@ -13321,9 +13537,13 @@ void intel_modeset_cleanup(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; struct drm_connector *connector; + intel_disable_gt_powersave(dev); + + intel_backlight_unregister(dev); + /* * Interrupts and polling as the first thing to avoid creating havoc. - * Too much stuff here (turning of rps, connectors, ...) would + * Too much stuff here (turning of connectors, ...) would * experience fancy races otherwise. */ intel_irq_uninstall(dev_priv); @@ -13340,8 +13560,6 @@ void intel_modeset_cleanup(struct drm_device *dev) intel_disable_fbc(dev); - intel_disable_gt_powersave(dev); - ironlake_teardown_rc6(dev); mutex_unlock(&dev->struct_mutex); |