X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=drivers%2Fgpu%2Fdrm%2Fi915%2Fintel_display.c;h=034aa7e8e6836df4d65675e49522259354f36dbd;hb=1486017fbfef5441cc61c805ccace4d3dea27c80;hp=3404da8e77b43e8e9e003fd27026580f45484745;hpb=0d703d4e5d7094e77186d09619548de42be9b493;p=deliverable%2Flinux.git diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3404da8e77b4..034aa7e8e683 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -37,6 +37,7 @@ #include #include "i915_drv.h" #include "i915_trace.h" +#include #include #include #include @@ -82,7 +83,8 @@ static void ironlake_pch_clock_get(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config); static int intel_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, - int x, int y, struct drm_framebuffer *old_fb); + int x, int y, struct drm_framebuffer *old_fb, + struct drm_atomic_state *state); static int intel_framebuffer_init(struct drm_device *dev, struct intel_framebuffer *ifb, struct drm_mode_fb_cmd2 *mode_cmd, @@ -775,6 +777,46 @@ g4x_find_best_dpll(const intel_limit_t *limit, struct intel_crtc *crtc, return found; } +/* + * Check if the calculated PLL configuration is more optimal compared to the + * best configuration and error found so far. Return the calculated error. + */ +static bool vlv_PLL_is_optimal(struct drm_device *dev, int target_freq, + const intel_clock_t *calculated_clock, + const intel_clock_t *best_clock, + unsigned int best_error_ppm, + unsigned int *error_ppm) +{ + /* + * For CHV ignore the error and consider only the P value. + * Prefer a bigger P value based on HW requirements. + */ + if (IS_CHERRYVIEW(dev)) { + *error_ppm = 0; + + return calculated_clock->p > best_clock->p; + } + + if (WARN_ON_ONCE(!target_freq)) + return false; + + *error_ppm = div_u64(1000000ULL * + abs(target_freq - calculated_clock->dot), + target_freq); + /* + * Prefer a better P value over a better (smaller) error if the error + * is small. Ensure this preference for future configurations too by + * setting the error to 0. + */ + if (*error_ppm < 100 && calculated_clock->p > best_clock->p) { + *error_ppm = 0; + + return true; + } + + return *error_ppm + 10 < best_error_ppm; +} + static bool vlv_find_best_dpll(const intel_limit_t *limit, struct intel_crtc *crtc, int target, int refclk, intel_clock_t *match_clock, @@ -799,7 +841,7 @@ vlv_find_best_dpll(const intel_limit_t *limit, struct intel_crtc *crtc, clock.p = clock.p1 * clock.p2; /* based on hardware requirement, prefer bigger m1,m2 values */ for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) { - unsigned int ppm, diff; + unsigned int ppm; clock.m2 = DIV_ROUND_CLOSEST(target * clock.p * clock.n, refclk * clock.m1); @@ -810,20 +852,15 @@ vlv_find_best_dpll(const intel_limit_t *limit, struct intel_crtc *crtc, &clock)) continue; - diff = abs(clock.dot - target); - ppm = div_u64(1000000ULL * diff, target); - - if (ppm < 100 && clock.p > best_clock->p) { - bestppm = 0; - *best_clock = clock; - found = true; - } + if (!vlv_PLL_is_optimal(dev, target, + &clock, + best_clock, + bestppm, &ppm)) + continue; - if (bestppm >= 10 && ppm < bestppm - 10) { - bestppm = ppm; - *best_clock = clock; - found = true; - } + *best_clock = clock; + bestppm = ppm; + found = true; } } } @@ -838,11 +875,13 @@ chv_find_best_dpll(const intel_limit_t *limit, struct intel_crtc *crtc, intel_clock_t *best_clock) { struct drm_device *dev = crtc->base.dev; + unsigned int best_error_ppm; intel_clock_t clock; uint64_t m2; int found = false; memset(best_clock, 0, sizeof(*best_clock)); + best_error_ppm = 1000000; /* * Based on hardware doc, the n always set to 1, and m1 always @@ -856,6 +895,7 @@ chv_find_best_dpll(const intel_limit_t *limit, struct intel_crtc *crtc, for (clock.p2 = limit->p2.p2_fast; clock.p2 >= limit->p2.p2_slow; clock.p2 -= clock.p2 > 10 ? 2 : 1) { + unsigned int error_ppm; clock.p = clock.p1 * clock.p2; @@ -872,12 +912,13 @@ chv_find_best_dpll(const intel_limit_t *limit, struct intel_crtc *crtc, if (!intel_PLL_is_valid(dev, limit, &clock)) continue; - /* based on hardware requirement, prefer bigger p - */ - if (clock.p > best_clock->p) { - *best_clock = clock; - found = true; - } + if (!vlv_PLL_is_optimal(dev, target, &clock, best_clock, + best_error_ppm, &error_ppm)) + continue; + + *best_clock = clock; + best_error_ppm = error_ppm; + found = true; } } @@ -896,8 +937,12 @@ bool intel_crtc_active(struct drm_crtc *crtc) * * We can ditch the crtc->primary->fb check as soon as we can * properly reconstruct framebuffers. + * + * FIXME: The intel_crtc->active here should be switched to + * crtc->state->active once we have proper CRTC states wired up + * for atomic. */ - return intel_crtc->active && crtc->primary->fb && + return intel_crtc->active && crtc->primary->state->fb && intel_crtc->config->base.adjusted_mode.crtc_clock; } @@ -2189,13 +2234,12 @@ static bool need_vtd_wa(struct drm_device *dev) return false; } -int -intel_fb_align_height(struct drm_device *dev, int height, - uint32_t pixel_format, - uint64_t fb_format_modifier) +unsigned int +intel_tile_height(struct drm_device *dev, uint32_t pixel_format, + uint64_t fb_format_modifier) { - int tile_height; - uint32_t bits_per_pixel; + unsigned int tile_height; + uint32_t pixel_bytes; switch (fb_format_modifier) { case DRM_FORMAT_MOD_NONE: @@ -2208,20 +2252,20 @@ intel_fb_align_height(struct drm_device *dev, int height, tile_height = 32; break; case I915_FORMAT_MOD_Yf_TILED: - bits_per_pixel = drm_format_plane_cpp(pixel_format, 0) * 8; - switch (bits_per_pixel) { + pixel_bytes = drm_format_plane_cpp(pixel_format, 0); + switch (pixel_bytes) { default: - case 8: + case 1: tile_height = 64; break; - case 16: - case 32: + case 2: + case 4: tile_height = 32; break; - case 64: + case 8: tile_height = 16; break; - case 128: + case 16: WARN_ONCE(1, "128-bit pixels are not supported for display!"); tile_height = 16; @@ -2234,17 +2278,60 @@ intel_fb_align_height(struct drm_device *dev, int height, break; } - return ALIGN(height, tile_height); + return tile_height; +} + +unsigned int +intel_fb_align_height(struct drm_device *dev, unsigned int height, + uint32_t pixel_format, uint64_t fb_format_modifier) +{ + return ALIGN(height, intel_tile_height(dev, pixel_format, + fb_format_modifier)); +} + +static int +intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb, + const struct drm_plane_state *plane_state) +{ + struct intel_rotation_info *info = &view->rotation_info; + static const struct i915_ggtt_view rotated_view = + { .type = I915_GGTT_VIEW_ROTATED }; + + *view = i915_ggtt_view_normal; + + if (!plane_state) + return 0; + + if (!intel_rotation_90_or_270(plane_state->rotation)) + return 0; + + *view = rotated_view; + + info->height = fb->height; + info->pixel_format = fb->pixel_format; + info->pitch = fb->pitches[0]; + info->fb_modifier = fb->modifier[0]; + + if (!(info->fb_modifier == I915_FORMAT_MOD_Y_TILED || + info->fb_modifier == I915_FORMAT_MOD_Yf_TILED)) { + DRM_DEBUG_KMS( + "Y or Yf tiling is needed for 90/270 rotation!\n"); + return -EINVAL; + } + + return 0; } int intel_pin_and_fence_fb_obj(struct drm_plane *plane, struct drm_framebuffer *fb, + const struct drm_plane_state *plane_state, struct intel_engine_cs *pipelined) { struct drm_device *dev = fb->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_object *obj = intel_fb_obj(fb); + struct i915_ggtt_view view; u32 alignment; int ret; @@ -2281,6 +2368,10 @@ intel_pin_and_fence_fb_obj(struct drm_plane *plane, return -EINVAL; } + ret = intel_fill_fb_ggtt_view(&view, fb, plane_state); + if (ret) + return ret; + /* Note that the w/a also requires 64 PTE of padding following the * bo. We currently fill all unused PTE with the shadow page and so * we should always have valid PTE following the scanout preventing @@ -2299,7 +2390,8 @@ intel_pin_and_fence_fb_obj(struct drm_plane *plane, intel_runtime_pm_get(dev_priv); dev_priv->mm.interruptible = false; - ret = i915_gem_object_pin_to_display_plane(obj, alignment, pipelined); + ret = i915_gem_object_pin_to_display_plane(obj, alignment, pipelined, + &view); if (ret) goto err_interruptible; @@ -2319,19 +2411,27 @@ intel_pin_and_fence_fb_obj(struct drm_plane *plane, return 0; err_unpin: - i915_gem_object_unpin_from_display_plane(obj); + i915_gem_object_unpin_from_display_plane(obj, &view); err_interruptible: dev_priv->mm.interruptible = true; intel_runtime_pm_put(dev_priv); return ret; } -static void intel_unpin_fb_obj(struct drm_i915_gem_object *obj) +static void intel_unpin_fb_obj(struct drm_framebuffer *fb, + const struct drm_plane_state *plane_state) { + struct drm_i915_gem_object *obj = intel_fb_obj(fb); + struct i915_ggtt_view view; + int ret; + WARN_ON(!mutex_is_locked(&obj->base.dev->struct_mutex)); + ret = intel_fill_fb_ggtt_view(&view, fb, plane_state); + WARN_ONCE(ret, "Couldn't get view from plane state!"); + i915_gem_object_unpin_fence(obj); - i915_gem_object_unpin_from_display_plane(obj); + i915_gem_object_unpin_from_display_plane(obj, &view); } /* Computes the linear offset to the base tile and adjusts x, y. bytes per pixel @@ -2409,8 +2509,8 @@ static int skl_format_to_fourcc(int format, bool rgb_order, bool alpha) } static bool -intel_alloc_plane_obj(struct intel_crtc *crtc, - struct intel_initial_plane_config *plane_config) +intel_alloc_initial_plane_obj(struct intel_crtc *crtc, + struct intel_initial_plane_config *plane_config) { struct drm_device *dev = crtc->base.dev; struct drm_i915_gem_object *obj = NULL; @@ -2444,17 +2544,14 @@ intel_alloc_plane_obj(struct intel_crtc *crtc, mode_cmd.flags = DRM_MODE_FB_MODIFIERS; mutex_lock(&dev->struct_mutex); - if (intel_framebuffer_init(dev, to_intel_framebuffer(fb), &mode_cmd, obj)) { DRM_DEBUG_KMS("intel fb init failed\n"); goto out_unref_obj; } - - obj->frontbuffer_bits = INTEL_FRONTBUFFER_PRIMARY(crtc->pipe); mutex_unlock(&dev->struct_mutex); - DRM_DEBUG_KMS("plane fb obj %p\n", obj); + DRM_DEBUG_KMS("initial plane fb obj %p\n", obj); return true; out_unref_obj: @@ -2478,26 +2575,23 @@ update_state_fb(struct drm_plane *plane) } static void -intel_find_plane_obj(struct intel_crtc *intel_crtc, - struct intel_initial_plane_config *plane_config) +intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, + struct intel_initial_plane_config *plane_config) { struct drm_device *dev = intel_crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc *c; struct intel_crtc *i; struct drm_i915_gem_object *obj; + struct drm_plane *primary = intel_crtc->base.primary; + struct drm_framebuffer *fb; if (!plane_config->fb) return; - if (intel_alloc_plane_obj(intel_crtc, plane_config)) { - struct drm_plane *primary = intel_crtc->base.primary; - - primary->fb = &plane_config->fb->base; - primary->state->crtc = &intel_crtc->base; - update_state_fb(primary); - - return; + if (intel_alloc_initial_plane_obj(intel_crtc, plane_config)) { + fb = &plane_config->fb->base; + goto valid_fb; } kfree(plane_config->fb); @@ -2515,25 +2609,29 @@ intel_find_plane_obj(struct intel_crtc *intel_crtc, if (!i->active) continue; - obj = intel_fb_obj(c->primary->fb); - if (obj == NULL) + fb = c->primary->fb; + if (!fb) continue; + obj = intel_fb_obj(fb); if (i915_gem_obj_ggtt_offset(obj) == plane_config->base) { - struct drm_plane *primary = intel_crtc->base.primary; - - if (obj->tiling_mode != I915_TILING_NONE) - dev_priv->preserve_bios_swizzle = true; - - drm_framebuffer_reference(c->primary->fb); - primary->fb = c->primary->fb; - primary->state->crtc = &intel_crtc->base; - update_state_fb(intel_crtc->base.primary); - obj->frontbuffer_bits |= INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe); - break; + drm_framebuffer_reference(fb); + goto valid_fb; } } + return; + +valid_fb: + obj = intel_fb_obj(fb); + if (obj->tiling_mode != I915_TILING_NONE) + dev_priv->preserve_bios_swizzle = true; + + primary->fb = fb; + primary->state->crtc = &intel_crtc->base; + primary->crtc = &intel_crtc->base; + update_state_fb(primary); + obj->frontbuffer_bits |= INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe); } static void i9xx_update_primary_plane(struct drm_crtc *crtc, @@ -2654,9 +2752,6 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc, I915_WRITE(reg, dspcntr); - DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n", - i915_gem_obj_ggtt_offset(obj), linear_offset, x, y, - fb->pitches[0]); I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]); if (INTEL_INFO(dev)->gen >= 4) { I915_WRITE(DSPSURF(plane), @@ -2758,9 +2853,6 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc, I915_WRITE(reg, dspcntr); - DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n", - i915_gem_obj_ggtt_offset(obj), linear_offset, x, y, - fb->pitches[0]); I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]); I915_WRITE(DSPSURF(plane), i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset); @@ -2807,6 +2899,17 @@ u32 intel_fb_stride_alignment(struct drm_device *dev, uint64_t fb_modifier, } } +unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane, + struct drm_i915_gem_object *obj) +{ + enum i915_ggtt_view_type view = I915_GGTT_VIEW_NORMAL; + + if (intel_rotation_90_or_270(intel_plane->base.state->rotation)) + view = I915_GGTT_VIEW_ROTATED; + + return i915_gem_obj_ggtt_offset_view(obj, view); +} + static void skylake_update_primary_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, int x, int y) @@ -2817,6 +2920,7 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc, struct drm_i915_gem_object *obj; int pipe = intel_crtc->pipe; u32 plane_ctl, stride_div; + unsigned long surf_addr; if (!intel_crtc->primary_enabled) { I915_WRITE(PLANE_CTL(pipe, 0), 0); @@ -2883,21 +2987,16 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc, obj = intel_fb_obj(fb); stride_div = intel_fb_stride_alignment(dev, fb->modifier[0], fb->pixel_format); + surf_addr = intel_plane_obj_offset(to_intel_plane(crtc->primary), obj); I915_WRITE(PLANE_CTL(pipe, 0), plane_ctl); - - DRM_DEBUG_KMS("Writing base %08lX %d,%d,%d,%d pitch=%d\n", - i915_gem_obj_ggtt_offset(obj), - x, y, fb->width, fb->height, - fb->pitches[0]); - I915_WRITE(PLANE_POS(pipe, 0), 0); I915_WRITE(PLANE_OFFSET(pipe, 0), (y << 16) | x); I915_WRITE(PLANE_SIZE(pipe, 0), (intel_crtc->config->pipe_src_h - 1) << 16 | (intel_crtc->config->pipe_src_w - 1)); I915_WRITE(PLANE_STRIDE(pipe, 0), fb->pitches[0] / stride_div); - I915_WRITE(PLANE_SURF(pipe, 0), i915_gem_obj_ggtt_offset(obj)); + I915_WRITE(PLANE_SURF(pipe, 0), surf_addr); POSTING_READ(PLANE_SURF(pipe, 0)); } @@ -3148,38 +3247,6 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc) FDI_FE_ERRC_ENABLE); } -static bool pipe_has_enabled_pch(struct intel_crtc *crtc) -{ - return crtc->base.state->enable && crtc->active && - crtc->config->has_pch_encoder; -} - -static void ivb_modeset_global_resources(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *pipe_B_crtc = - to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_B]); - struct intel_crtc *pipe_C_crtc = - to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_C]); - uint32_t temp; - - /* - * When everything is off disable fdi C so that we could enable fdi B - * with all lanes. Note that we don't care about enabled pipes without - * an enabled pch encoder. - */ - if (!pipe_has_enabled_pch(pipe_B_crtc) && - !pipe_has_enabled_pch(pipe_C_crtc)) { - WARN_ON(I915_READ(FDI_RX_CTL(PIPE_B)) & FDI_RX_ENABLE); - WARN_ON(I915_READ(FDI_RX_CTL(PIPE_C)) & FDI_RX_ENABLE); - - temp = I915_READ(SOUTH_CHICKEN1); - temp &= ~FDI_BC_BIFURCATION_SELECT; - DRM_DEBUG_KMS("disabling fdi C rx\n"); - I915_WRITE(SOUTH_CHICKEN1, temp); - } -} - /* The FDI link training functions for ILK/Ibexpeak. */ static void ironlake_fdi_link_train(struct drm_crtc *crtc) { @@ -3835,20 +3902,23 @@ static void ironlake_pch_transcoder_set_timings(struct intel_crtc *crtc, I915_READ(VSYNCSHIFT(cpu_transcoder))); } -static void cpt_enable_fdi_bc_bifurcation(struct drm_device *dev) +static void cpt_set_fdi_bc_bifurcation(struct drm_device *dev, bool enable) { struct drm_i915_private *dev_priv = dev->dev_private; uint32_t temp; temp = I915_READ(SOUTH_CHICKEN1); - if (temp & FDI_BC_BIFURCATION_SELECT) + if (!!(temp & FDI_BC_BIFURCATION_SELECT) == enable) return; WARN_ON(I915_READ(FDI_RX_CTL(PIPE_B)) & FDI_RX_ENABLE); WARN_ON(I915_READ(FDI_RX_CTL(PIPE_C)) & FDI_RX_ENABLE); - temp |= FDI_BC_BIFURCATION_SELECT; - DRM_DEBUG_KMS("enabling fdi C rx\n"); + temp &= ~FDI_BC_BIFURCATION_SELECT; + if (enable) + temp |= FDI_BC_BIFURCATION_SELECT; + + DRM_DEBUG_KMS("%sabling fdi C rx\n", enable ? "en" : "dis"); I915_WRITE(SOUTH_CHICKEN1, temp); POSTING_READ(SOUTH_CHICKEN1); } @@ -3856,20 +3926,19 @@ static void cpt_enable_fdi_bc_bifurcation(struct drm_device *dev) static void ivybridge_update_fdi_bc_bifurcation(struct intel_crtc *intel_crtc) { struct drm_device *dev = intel_crtc->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; switch (intel_crtc->pipe) { case PIPE_A: break; case PIPE_B: if (intel_crtc->config->fdi_lanes > 2) - WARN_ON(I915_READ(SOUTH_CHICKEN1) & FDI_BC_BIFURCATION_SELECT); + cpt_set_fdi_bc_bifurcation(dev, false); else - cpt_enable_fdi_bc_bifurcation(dev); + cpt_set_fdi_bc_bifurcation(dev, true); break; case PIPE_C: - cpt_enable_fdi_bc_bifurcation(dev); + cpt_set_fdi_bc_bifurcation(dev, true); break; default: @@ -5001,24 +5070,23 @@ static void cherryview_set_cdclk(struct drm_device *dev, int cdclk) WARN_ON(dev_priv->display.get_display_clock_speed(dev) != dev_priv->vlv_cdclk_freq); switch (cdclk) { - case 400000: - cmd = 3; - break; case 333333: case 320000: - cmd = 2; - break; case 266667: - cmd = 1; - break; case 200000: - cmd = 0; break; default: MISSING_CASE(cdclk); return; } + /* + * Specs are full of misinformation, but testing on actual + * hardware has shown that we just need to write the desired + * CCK divider into the Punit register. + */ + cmd = DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1, cdclk) - 1; + mutex_lock(&dev_priv->rps.hw_lock); val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ); val &= ~DSPFREQGUAR_MASK_CHV; @@ -5038,27 +5106,25 @@ static int valleyview_calc_cdclk(struct drm_i915_private *dev_priv, int max_pixclk) { int freq_320 = (dev_priv->hpll_freq << 1) % 320000 != 0 ? 333333 : 320000; - - /* FIXME: Punit isn't quite ready yet */ - if (IS_CHERRYVIEW(dev_priv->dev)) - return 400000; + int limit = IS_CHERRYVIEW(dev_priv) ? 95 : 90; /* * Really only a few cases to deal with, as only 4 CDclks are supported: * 200MHz * 267MHz * 320/333MHz (depends on HPLL freq) - * 400MHz - * So we check to see whether we're above 90% of the lower bin and - * adjust if needed. + * 400MHz (VLV only) + * So we check to see whether we're above 90% (VLV) or 95% (CHV) + * of the lower bin and adjust if needed. * * We seem to get an unstable or solid color picture at 200MHz. * Not sure what's wrong. For now use 200MHz only when all pipes * are off. */ - if (max_pixclk > freq_320*9/10) + if (!IS_CHERRYVIEW(dev_priv) && + max_pixclk > freq_320*limit/100) return 400000; - else if (max_pixclk > 266667*9/10) + else if (max_pixclk > 266667*limit/100) return freq_320; else if (max_pixclk > 0) return 266667; @@ -5099,6 +5165,42 @@ static void valleyview_modeset_global_pipes(struct drm_device *dev, *prepare_pipes |= (1 << intel_crtc->pipe); } +static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv) +{ + unsigned int credits, default_credits; + + if (IS_CHERRYVIEW(dev_priv)) + default_credits = PFI_CREDIT(12); + else + default_credits = PFI_CREDIT(8); + + if (DIV_ROUND_CLOSEST(dev_priv->vlv_cdclk_freq, 1000) >= dev_priv->rps.cz_freq) { + /* CHV suggested value is 31 or 63 */ + if (IS_CHERRYVIEW(dev_priv)) + credits = PFI_CREDIT_31; + else + credits = PFI_CREDIT(15); + } else { + credits = default_credits; + } + + /* + * WA - write default credits before re-programming + * FIXME: should we also set the resend bit here? + */ + I915_WRITE(GCI_CONTROL, VGA_FAST_MODE_DISABLE | + default_credits); + + I915_WRITE(GCI_CONTROL, VGA_FAST_MODE_DISABLE | + credits | PFI_CREDIT_RESEND); + + /* + * FIXME is this guaranteed to clear + * immediately or should we poll for it? + */ + WARN_ON(I915_READ(GCI_CONTROL) & PFI_CREDIT_RESEND); +} + static void valleyview_modeset_global_resources(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -5122,6 +5224,8 @@ static void valleyview_modeset_global_resources(struct drm_device *dev) else valleyview_set_cdclk(dev, req_cdclk); + vlv_program_pfi_credits(dev_priv); + intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A); } } @@ -5535,13 +5639,21 @@ bool intel_connector_get_hw_state(struct intel_connector *connector) return encoder->get_hw_state(encoder, &pipe); } +static int pipe_required_fdi_lanes(struct drm_device *dev, enum pipe pipe) +{ + struct intel_crtc *crtc = + to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe)); + + if (crtc->base.state->enable && + crtc->config->has_pch_encoder) + return crtc->config->fdi_lanes; + + return 0; +} + static bool ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe, struct intel_crtc_state *pipe_config) { - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *pipe_B_crtc = - to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_B]); - DRM_DEBUG_KMS("checking fdi config on pipe %c, lanes %i\n", pipe_name(pipe), pipe_config->fdi_lanes); if (pipe_config->fdi_lanes > 4) { @@ -5568,22 +5680,20 @@ static bool ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe, case PIPE_A: return true; case PIPE_B: - if (dev_priv->pipe_to_crtc_mapping[PIPE_C]->enabled && - pipe_config->fdi_lanes > 2) { + if (pipe_config->fdi_lanes > 2 && + pipe_required_fdi_lanes(dev, PIPE_C) > 0) { DRM_DEBUG_KMS("invalid shared fdi lane config on pipe %c: %i lanes\n", pipe_name(pipe), pipe_config->fdi_lanes); return false; } return true; case PIPE_C: - if (!pipe_has_enabled_pch(pipe_B_crtc) || - pipe_B_crtc->config->fdi_lanes <= 2) { - if (pipe_config->fdi_lanes > 2) { - DRM_DEBUG_KMS("invalid shared fdi lane config on pipe %c: %i lanes\n", - pipe_name(pipe), pipe_config->fdi_lanes); - return false; - } - } else { + if (pipe_config->fdi_lanes > 2) { + DRM_DEBUG_KMS("only 2 lanes on pipe %c: required %i lanes\n", + pipe_name(pipe), pipe_config->fdi_lanes); + return false; + } + if (pipe_required_fdi_lanes(dev, PIPE_B) > 2) { DRM_DEBUG_KMS("fdi link B uses too many lanes to enable link C\n"); return false; } @@ -5717,10 +5827,6 @@ static int valleyview_get_display_clock_speed(struct drm_device *dev) u32 val; int divider; - /* FIXME: Punit isn't quite ready yet */ - if (IS_CHERRYVIEW(dev)) - return 400000; - if (dev_priv->hpll_freq == 0) dev_priv->hpll_freq = valleyview_get_vco(dev_priv); @@ -5918,7 +6024,7 @@ static void i9xx_update_pll_dividers(struct intel_crtc *crtc, crtc->lowfreq_avail = false; if (intel_pipe_will_have_type(crtc, INTEL_OUTPUT_LVDS) && - reduced_clock && i915.powersave) { + reduced_clock) { crtc_state->dpll_hw_state.fp1 = fp2; crtc->lowfreq_avail = true; } else { @@ -6162,9 +6268,10 @@ static void chv_prepare_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 loopfilter, intcoeff; + u32 loopfilter, tribuf_calcntr; u32 bestn, bestm1, bestm2, bestp1, bestp2, bestm2_frac; - int refclk; + u32 dpio_val; + int vco; bestn = pipe_config->dpll.n; bestm2_frac = pipe_config->dpll.m2 & 0x3fffff; @@ -6172,6 +6279,9 @@ static void chv_prepare_pll(struct intel_crtc *crtc, bestm2 = pipe_config->dpll.m2 >> 22; bestp1 = pipe_config->dpll.p1; bestp2 = pipe_config->dpll.p2; + vco = pipe_config->dpll.vco; + dpio_val = 0; + loopfilter = 0; /* * Enable Refclk and SSC @@ -6197,26 +6307,56 @@ static void chv_prepare_pll(struct intel_crtc *crtc, 1 << DPIO_CHV_N_DIV_SHIFT); /* M2 fraction division */ - vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW2(port), bestm2_frac); + if (bestm2_frac) + vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW2(port), bestm2_frac); /* M2 fraction division enable */ - vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW3(port), - DPIO_CHV_FRAC_DIV_EN | - (2 << DPIO_CHV_FEEDFWD_GAIN_SHIFT)); + dpio_val = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW3(port)); + dpio_val &= ~(DPIO_CHV_FEEDFWD_GAIN_MASK | DPIO_CHV_FRAC_DIV_EN); + dpio_val |= (2 << DPIO_CHV_FEEDFWD_GAIN_SHIFT); + if (bestm2_frac) + dpio_val |= DPIO_CHV_FRAC_DIV_EN; + vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW3(port), dpio_val); + + /* Program digital lock detect threshold */ + dpio_val = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW9(port)); + dpio_val &= ~(DPIO_CHV_INT_LOCK_THRESHOLD_MASK | + DPIO_CHV_INT_LOCK_THRESHOLD_SEL_COARSE); + dpio_val |= (0x5 << DPIO_CHV_INT_LOCK_THRESHOLD_SHIFT); + if (!bestm2_frac) + dpio_val |= DPIO_CHV_INT_LOCK_THRESHOLD_SEL_COARSE; + vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW9(port), dpio_val); /* Loop filter */ - refclk = i9xx_get_refclk(crtc, 0); - loopfilter = 5 << DPIO_CHV_PROP_COEFF_SHIFT | - 2 << DPIO_CHV_GAIN_CTRL_SHIFT; - if (refclk == 100000) - intcoeff = 11; - else if (refclk == 38400) - intcoeff = 10; - else - intcoeff = 9; - loopfilter |= intcoeff << DPIO_CHV_INT_COEFF_SHIFT; + if (vco == 5400000) { + loopfilter |= (0x3 << DPIO_CHV_PROP_COEFF_SHIFT); + loopfilter |= (0x8 << DPIO_CHV_INT_COEFF_SHIFT); + loopfilter |= (0x1 << DPIO_CHV_GAIN_CTRL_SHIFT); + tribuf_calcntr = 0x9; + } else if (vco <= 6200000) { + loopfilter |= (0x5 << DPIO_CHV_PROP_COEFF_SHIFT); + loopfilter |= (0xB << DPIO_CHV_INT_COEFF_SHIFT); + loopfilter |= (0x3 << DPIO_CHV_GAIN_CTRL_SHIFT); + tribuf_calcntr = 0x9; + } else if (vco <= 6480000) { + loopfilter |= (0x4 << DPIO_CHV_PROP_COEFF_SHIFT); + loopfilter |= (0x9 << DPIO_CHV_INT_COEFF_SHIFT); + loopfilter |= (0x3 << DPIO_CHV_GAIN_CTRL_SHIFT); + tribuf_calcntr = 0x8; + } else { + /* Not supported. Apply the same limits as in the max case */ + loopfilter |= (0x4 << DPIO_CHV_PROP_COEFF_SHIFT); + loopfilter |= (0x9 << DPIO_CHV_INT_COEFF_SHIFT); + loopfilter |= (0x3 << DPIO_CHV_GAIN_CTRL_SHIFT); + tribuf_calcntr = 0; + } vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW6(port), loopfilter); + dpio_val = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW8(port)); + dpio_val &= ~DPIO_CHV_TDC_TARGET_CNT_MASK; + dpio_val |= (tribuf_calcntr << DPIO_CHV_TDC_TARGET_CNT_SHIFT); + vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW8(port), dpio_val); + /* AFC Recal */ vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW14(port), vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW14(port)) | @@ -6738,7 +6878,7 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc, u32 val, base, offset; int pipe = crtc->pipe, plane = crtc->plane; int fourcc, pixel_format; - int aligned_height; + unsigned int aligned_height; struct drm_framebuffer *fb; struct intel_framebuffer *intel_fb; @@ -7667,7 +7807,7 @@ static int ironlake_crtc_compute_clock(struct intel_crtc *crtc, } } - if (is_lvds && has_reduced_clock && i915.powersave) + if (is_lvds && has_reduced_clock) crtc->lowfreq_avail = true; else crtc->lowfreq_avail = false; @@ -7776,7 +7916,7 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc, u32 val, base, offset, stride_mult, tiling; int pipe = crtc->pipe; int fourcc, pixel_format; - int aligned_height; + unsigned int aligned_height; struct drm_framebuffer *fb; struct intel_framebuffer *intel_fb; @@ -7884,7 +8024,7 @@ ironlake_get_initial_plane_config(struct intel_crtc *crtc, u32 val, base, offset; int pipe = crtc->pipe; int fourcc, pixel_format; - int aligned_height; + unsigned int aligned_height; struct drm_framebuffer *fb; struct intel_framebuffer *intel_fb; @@ -8768,6 +8908,8 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector, struct drm_device *dev = encoder->dev; struct drm_framebuffer *fb; struct drm_mode_config *config = &dev->mode_config; + struct drm_atomic_state *state = NULL; + struct drm_connector_state *connector_state; int ret, i = -1; DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n", @@ -8849,6 +8991,21 @@ retry: old->load_detect_temp = true; old->release_fb = NULL; + state = drm_atomic_state_alloc(dev); + if (!state) + return false; + + state->acquire_ctx = ctx; + + connector_state = drm_atomic_get_connector_state(state, connector); + if (IS_ERR(connector_state)) { + ret = PTR_ERR(connector_state); + goto fail; + } + + connector_state->crtc = crtc; + connector_state->best_encoder = &intel_encoder->base; + if (!mode) mode = &load_detect_mode; @@ -8871,7 +9028,7 @@ retry: goto fail; } - if (intel_set_mode(crtc, mode, 0, 0, fb)) { + if (intel_set_mode(crtc, mode, 0, 0, fb, state)) { DRM_DEBUG_KMS("failed to set mode on load-detect pipe\n"); if (old->release_fb) old->release_fb->funcs->destroy(old->release_fb); @@ -8890,6 +9047,11 @@ retry: else intel_crtc->new_config = NULL; fail_unlock: + if (state) { + drm_atomic_state_free(state); + state = NULL; + } + if (ret == -EDEADLK) { drm_modeset_backoff(ctx); goto retry; @@ -8899,24 +9061,44 @@ fail_unlock: } void intel_release_load_detect_pipe(struct drm_connector *connector, - struct intel_load_detect_pipe *old) + struct intel_load_detect_pipe *old, + struct drm_modeset_acquire_ctx *ctx) { + struct drm_device *dev = connector->dev; struct intel_encoder *intel_encoder = intel_attached_encoder(connector); struct drm_encoder *encoder = &intel_encoder->base; struct drm_crtc *crtc = encoder->crtc; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct drm_atomic_state *state; + struct drm_connector_state *connector_state; DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n", connector->base.id, connector->name, encoder->base.id, encoder->name); if (old->load_detect_temp) { + state = drm_atomic_state_alloc(dev); + if (!state) + goto fail; + + state->acquire_ctx = ctx; + + connector_state = drm_atomic_get_connector_state(state, connector); + if (IS_ERR(connector_state)) + goto fail; + to_intel_connector(connector)->new_encoder = NULL; intel_encoder->new_crtc = NULL; intel_crtc->new_enabled = false; intel_crtc->new_config = NULL; - intel_set_mode(crtc, NULL, 0, 0, NULL); + + connector_state->best_encoder = NULL; + connector_state->crtc = NULL; + + intel_set_mode(crtc, NULL, 0, 0, NULL, state); + + drm_atomic_state_free(state); if (old->release_fb) { drm_framebuffer_unregister_private(old->release_fb); @@ -8929,6 +9111,11 @@ void intel_release_load_detect_pipe(struct drm_connector *connector, /* Switch crtc and encoder back off if necessary */ if (old->dpms_mode != DRM_MODE_DPMS_ON) connector->funcs->dpms(connector, old->dpms_mode); + + return; +fail: + DRM_DEBUG_KMS("Couldn't release load detect pipe.\n"); + drm_atomic_state_free(state); } static int i9xx_pll_refclk(struct drm_device *dev, @@ -9167,6 +9354,8 @@ void intel_mark_busy(struct drm_device *dev) intel_runtime_pm_get(dev_priv); i915_update_gfx_val(dev_priv); + if (INTEL_INFO(dev)->gen >= 6) + gen6_rps_busy(dev_priv); dev_priv->mm.busy = true; } @@ -9180,9 +9369,6 @@ void intel_mark_idle(struct drm_device *dev) dev_priv->mm.busy = false; - if (!i915.powersave) - goto out; - for_each_crtc(dev, crtc) { if (!crtc->primary->fb) continue; @@ -9193,7 +9379,6 @@ void intel_mark_idle(struct drm_device *dev) if (INTEL_INFO(dev)->gen >= 6) gen6_rps_idle(dev->dev_private); -out: intel_runtime_pm_put(dev_priv); } @@ -9235,9 +9420,8 @@ static void intel_unpin_work_fn(struct work_struct *__work) enum pipe pipe = to_intel_crtc(work->crtc)->pipe; mutex_lock(&dev->struct_mutex); - intel_unpin_fb_obj(intel_fb_obj(work->old_fb)); + intel_unpin_fb_obj(work->old_fb, work->crtc->primary->state); drm_gem_object_unreference(&work->pending_flip_obj->base); - drm_framebuffer_unreference(work->old_fb); intel_fbc_update(dev); @@ -9246,6 +9430,7 @@ static void intel_unpin_work_fn(struct work_struct *__work) mutex_unlock(&dev->struct_mutex); intel_frontbuffer_flip_complete(dev, INTEL_FRONTBUFFER_PRIMARY(pipe)); + drm_framebuffer_unreference(work->old_fb); BUG_ON(atomic_read(&to_intel_crtc(work->crtc)->unpin_work_count) == 0); atomic_dec(&to_intel_crtc(work->crtc)->unpin_work_count); @@ -9817,7 +10002,7 @@ void intel_check_page_flip(struct drm_device *dev, int pipe) struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - WARN_ON(!in_irq()); + WARN_ON(!in_interrupt()); if (crtc == NULL) return; @@ -9909,10 +10094,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, if (atomic_read(&intel_crtc->unpin_work_count) >= 2) flush_workqueue(dev_priv->wq); - ret = i915_mutex_lock_interruptible(dev); - if (ret) - goto cleanup; - /* Reference the objects for the scheduled work. */ drm_framebuffer_reference(work->old_fb); drm_gem_object_reference(&obj->base); @@ -9922,6 +10103,10 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, work->pending_flip_obj = obj; + ret = i915_mutex_lock_interruptible(dev); + if (ret) + goto cleanup; + atomic_inc(&intel_crtc->unpin_work_count); intel_crtc->reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter); @@ -9943,12 +10128,13 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, ring = &dev_priv->ring[RCS]; } - ret = intel_pin_and_fence_fb_obj(crtc->primary, fb, ring); + ret = intel_pin_and_fence_fb_obj(crtc->primary, fb, + crtc->primary->state, ring); if (ret) goto cleanup_pending; - work->gtt_offset = - i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset; + work->gtt_offset = intel_plane_obj_offset(to_intel_plane(primary), obj) + + intel_crtc->dspaddr_offset; if (use_mmio_flip(ring, obj)) { ret = intel_queue_mmio_flip(dev, crtc, fb, obj, ring, @@ -9983,16 +10169,17 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, return 0; cleanup_unpin: - intel_unpin_fb_obj(obj); + intel_unpin_fb_obj(fb, crtc->primary->state); cleanup_pending: atomic_dec(&intel_crtc->unpin_work_count); + mutex_unlock(&dev->struct_mutex); +cleanup: crtc->primary->fb = old_fb; update_state_fb(crtc->primary); + + drm_gem_object_unreference_unlocked(&obj->base); drm_framebuffer_unreference(work->old_fb); - drm_gem_object_unreference(&obj->base); - mutex_unlock(&dev->struct_mutex); -cleanup: spin_lock_irq(&dev->event_lock); intel_crtc->unpin_work = NULL; spin_unlock_irq(&dev->event_lock); @@ -10052,6 +10239,27 @@ static void intel_modeset_update_staged_output_state(struct drm_device *dev) } } +/* Transitional helper to copy current connector/encoder state to + * connector->state. This is needed so that code that is partially + * converted to atomic does the right thing. + */ +static void intel_modeset_update_connector_atomic_state(struct drm_device *dev) +{ + struct intel_connector *connector; + + for_each_intel_connector(dev, connector) { + if (connector->base.encoder) { + connector->base.state->best_encoder = + connector->base.encoder; + connector->base.state->crtc = + connector->base.encoder->crtc; + } else { + connector->base.state->best_encoder = NULL; + connector->base.state->crtc = NULL; + } + } +} + /** * intel_modeset_commit_output_state * @@ -10075,6 +10283,8 @@ static void intel_modeset_commit_output_state(struct drm_device *dev) crtc->base.state->enable = crtc->new_enabled; crtc->base.enabled = crtc->new_enabled; } + + intel_modeset_update_connector_atomic_state(dev); } static void @@ -10109,8 +10319,9 @@ compute_baseline_pipe_bpp(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config) { struct drm_device *dev = crtc->base.dev; + struct drm_atomic_state *state; struct intel_connector *connector; - int bpp; + int bpp, i; switch (fb->pixel_format) { case DRM_FORMAT_C8: @@ -10150,10 +10361,15 @@ compute_baseline_pipe_bpp(struct intel_crtc *crtc, pipe_config->pipe_bpp = bpp; + state = pipe_config->base.state; + /* Clamp display bpp to EDID value */ - for_each_intel_connector(dev, connector) { - if (!connector->new_encoder || - connector->new_encoder->new_crtc != crtc) + for (i = 0; i < state->num_connector; i++) { + if (!state->connectors[i]) + continue; + + connector = to_intel_connector(state->connectors[i]); + if (state->connector_states[i]->crtc != &crtc->base) continue; connected_sink_compute_bpp(connector, pipe_config); @@ -10309,15 +10525,30 @@ static bool check_digital_port_conflicts(struct drm_device *dev) return true; } +static void +clear_intel_crtc_state(struct intel_crtc_state *crtc_state) +{ + struct drm_crtc_state tmp_state; + + /* Clear only the intel specific part of the crtc state */ + tmp_state = crtc_state->base; + memset(crtc_state, 0, sizeof *crtc_state); + crtc_state->base = tmp_state; +} + static struct intel_crtc_state * intel_modeset_pipe_config(struct drm_crtc *crtc, struct drm_framebuffer *fb, - struct drm_display_mode *mode) + struct drm_display_mode *mode, + struct drm_atomic_state *state) { struct drm_device *dev = crtc->dev; struct intel_encoder *encoder; + struct intel_connector *connector; + struct drm_connector_state *connector_state; struct intel_crtc_state *pipe_config; int plane_bpp, ret = -EINVAL; + int i; bool retry = true; if (!check_encoder_cloning(to_intel_crtc(crtc))) { @@ -10330,9 +10561,11 @@ intel_modeset_pipe_config(struct drm_crtc *crtc, return ERR_PTR(-EINVAL); } - pipe_config = kzalloc(sizeof(*pipe_config), GFP_KERNEL); - if (!pipe_config) - return ERR_PTR(-ENOMEM); + pipe_config = intel_atomic_get_crtc_state(state, to_intel_crtc(crtc)); + if (IS_ERR(pipe_config)) + return pipe_config; + + clear_intel_crtc_state(pipe_config); pipe_config->base.crtc = crtc; drm_mode_copy(&pipe_config->base.adjusted_mode, mode); @@ -10389,11 +10622,17 @@ encoder_retry: * adjust it according to limitations or connector properties, and also * a chance to reject the mode entirely. */ - for_each_intel_encoder(dev, encoder) { + for (i = 0; i < state->num_connector; i++) { + connector = to_intel_connector(state->connectors[i]); + if (!connector) + continue; - if (&encoder->new_crtc->base != crtc) + connector_state = state->connector_states[i]; + if (connector_state->crtc != crtc) continue; + encoder = to_intel_encoder(connector_state->best_encoder); + if (!(encoder->compute_config(encoder, pipe_config))) { DRM_DEBUG_KMS("Encoder config failure\n"); goto fail; @@ -10429,7 +10668,6 @@ encoder_retry: return pipe_config; fail: - kfree(pipe_config); return ERR_PTR(ret); } @@ -11108,17 +11346,30 @@ static struct intel_crtc_state * intel_modeset_compute_config(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_framebuffer *fb, + struct drm_atomic_state *state, unsigned *modeset_pipes, unsigned *prepare_pipes, unsigned *disable_pipes) { + struct drm_device *dev = crtc->dev; struct intel_crtc_state *pipe_config = NULL; + struct intel_crtc *intel_crtc; + int ret = 0; + + ret = drm_atomic_add_affected_connectors(state, crtc); + if (ret) + return ERR_PTR(ret); intel_modeset_affected_pipes(crtc, modeset_pipes, prepare_pipes, disable_pipes); - if ((*modeset_pipes) == 0) - goto out; + for_each_intel_crtc_masked(dev, *disable_pipes, intel_crtc) { + pipe_config = intel_atomic_get_crtc_state(state, intel_crtc); + if (IS_ERR(pipe_config)) + return pipe_config; + + pipe_config->base.enable = false; + } /* * Note this needs changes when we start tracking multiple modes @@ -11126,15 +11377,21 @@ intel_modeset_compute_config(struct drm_crtc *crtc, * (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; + for_each_intel_crtc_masked(dev, *modeset_pipes, intel_crtc) { + /* FIXME: For now we still expect modeset_pipes has at most + * one bit set. */ + if (WARN_ON(&intel_crtc->base != crtc)) + continue; + + pipe_config = intel_modeset_pipe_config(crtc, fb, mode, state); + if (IS_ERR(pipe_config)) + return pipe_config; + + intel_dump_pipe_config(to_intel_crtc(crtc), pipe_config, + "[modeset]"); } - intel_dump_pipe_config(to_intel_crtc(crtc), pipe_config, - "[modeset]"); -out: - return pipe_config; + return intel_atomic_get_crtc_state(state, to_intel_crtc(crtc));; } static int __intel_set_mode_setup_plls(struct drm_device *dev, @@ -11178,6 +11435,7 @@ static int __intel_set_mode(struct drm_crtc *crtc, struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_display_mode *saved_mode; + struct intel_crtc_state *crtc_state_copy = NULL; struct intel_crtc *intel_crtc; int ret = 0; @@ -11185,6 +11443,12 @@ static int __intel_set_mode(struct drm_crtc *crtc, if (!saved_mode) return -ENOMEM; + crtc_state_copy = kmalloc(sizeof(*crtc_state_copy), GFP_KERNEL); + if (!crtc_state_copy) { + ret = -ENOMEM; + goto done; + } + *saved_mode = crtc->mode; if (modeset_pipes) @@ -11271,6 +11535,22 @@ done: if (ret && crtc->state->enable) crtc->mode = *saved_mode; + if (ret == 0 && pipe_config) { + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + + /* The pipe_config will be freed with the atomic state, so + * make a copy. */ + memcpy(crtc_state_copy, intel_crtc->config, + sizeof *crtc_state_copy); + intel_crtc->config = crtc_state_copy; + intel_crtc->base.state = &crtc_state_copy->base; + + if (modeset_pipes) + intel_crtc->new_config = intel_crtc->config; + } else { + kfree(crtc_state_copy); + } + kfree(saved_mode); return ret; } @@ -11296,27 +11576,81 @@ static int intel_set_mode_pipes(struct drm_crtc *crtc, 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 drm_atomic_state *state) { struct intel_crtc_state *pipe_config; unsigned modeset_pipes, prepare_pipes, disable_pipes; + int ret = 0; - pipe_config = intel_modeset_compute_config(crtc, mode, fb, + pipe_config = intel_modeset_compute_config(crtc, mode, fb, state, &modeset_pipes, &prepare_pipes, &disable_pipes); - if (IS_ERR(pipe_config)) - return PTR_ERR(pipe_config); + if (IS_ERR(pipe_config)) { + ret = PTR_ERR(pipe_config); + goto out; + } - return intel_set_mode_pipes(crtc, mode, x, y, fb, pipe_config, - modeset_pipes, prepare_pipes, - disable_pipes); + ret = intel_set_mode_pipes(crtc, mode, x, y, fb, pipe_config, + modeset_pipes, prepare_pipes, + disable_pipes); + if (ret) + goto out; + +out: + return ret; } void intel_crtc_restore_mode(struct drm_crtc *crtc) { - intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, crtc->primary->fb); + struct drm_device *dev = crtc->dev; + struct drm_atomic_state *state; + struct intel_encoder *encoder; + struct intel_connector *connector; + struct drm_connector_state *connector_state; + + state = drm_atomic_state_alloc(dev); + if (!state) { + DRM_DEBUG_KMS("[CRTC:%d] mode restore failed, out of memory", + crtc->base.id); + return; + } + + state->acquire_ctx = dev->mode_config.acquire_ctx; + + /* The force restore path in the HW readout code relies on the staged + * config still keeping the user requested config while the actual + * state has been overwritten by the configuration read from HW. We + * need to copy the staged config to the atomic state, otherwise the + * mode set will just reapply the state the HW is already in. */ + for_each_intel_encoder(dev, encoder) { + if (&encoder->new_crtc->base != crtc) + continue; + + for_each_intel_connector(dev, connector) { + if (connector->new_encoder != encoder) + continue; + + connector_state = drm_atomic_get_connector_state(state, &connector->base); + if (IS_ERR(connector_state)) { + DRM_DEBUG_KMS("Failed to add [CONNECTOR:%d:%s] to state: %ld\n", + connector->base.base.id, + connector->base.name, + PTR_ERR(connector_state)); + continue; + } + + connector_state->crtc = crtc; + connector_state->best_encoder = &encoder->base; + } + } + + intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, crtc->primary->fb, + state); + + drm_atomic_state_free(state); } #undef for_each_intel_crtc_masked @@ -11485,9 +11819,11 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set, static int intel_modeset_stage_output_state(struct drm_device *dev, struct drm_mode_set *set, - struct intel_set_config *config) + struct intel_set_config *config, + struct drm_atomic_state *state) { struct intel_connector *connector; + struct drm_connector_state *connector_state; struct intel_encoder *encoder; struct intel_crtc *crtc; int ro; @@ -11551,6 +11887,14 @@ intel_modeset_stage_output_state(struct drm_device *dev, } connector->new_encoder->new_crtc = to_intel_crtc(new_crtc); + connector_state = + drm_atomic_get_connector_state(state, &connector->base); + if (IS_ERR(connector_state)) + return PTR_ERR(connector_state); + + connector_state->crtc = new_crtc; + connector_state->best_encoder = &connector->new_encoder->base; + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d]\n", connector->base.base.id, connector->base.name, @@ -11583,9 +11927,15 @@ intel_modeset_stage_output_state(struct drm_device *dev, } /* Now we've also updated encoder->new_crtc for all encoders. */ for_each_intel_connector(dev, connector) { - if (connector->new_encoder) + connector_state = + drm_atomic_get_connector_state(state, &connector->base); + + if (connector->new_encoder) { if (connector->new_encoder != connector->encoder) connector->encoder = connector->new_encoder; + } else { + connector_state->crtc = NULL; + } } for_each_intel_crtc(dev, crtc) { crtc->new_enabled = false; @@ -11641,6 +11991,7 @@ static int intel_crtc_set_config(struct drm_mode_set *set) { struct drm_device *dev; struct drm_mode_set save_set; + struct drm_atomic_state *state = NULL; struct intel_set_config *config; struct intel_crtc_state *pipe_config; unsigned modeset_pipes, prepare_pipes, disable_pipes; @@ -11685,12 +12036,20 @@ static int intel_crtc_set_config(struct drm_mode_set *set) * such cases. */ intel_set_config_compute_mode_changes(set, config); - ret = intel_modeset_stage_output_state(dev, set, config); + state = drm_atomic_state_alloc(dev); + if (!state) { + ret = -ENOMEM; + goto out_config; + } + + state->acquire_ctx = dev->mode_config.acquire_ctx; + + ret = intel_modeset_stage_output_state(dev, set, config, state); if (ret) goto fail; pipe_config = intel_modeset_compute_config(set->crtc, set->mode, - set->fb, + set->fb, state, &modeset_pipes, &prepare_pipes, &disable_pipes); @@ -11710,10 +12069,6 @@ static int intel_crtc_set_config(struct drm_mode_set *set) */ } - /* 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) { @@ -11759,6 +12114,8 @@ static int intel_crtc_set_config(struct drm_mode_set *set) fail: intel_set_config_restore_state(dev, config); + drm_atomic_state_clear(state); + /* * HACK: if the pipe was on, but we didn't have a framebuffer, * force the pipe off to avoid oopsing in the modeset code @@ -11771,11 +12128,15 @@ fail: /* Try to restore the config */ if (config->mode_changed && intel_set_mode(save_set.crtc, save_set.mode, - save_set.x, save_set.y, save_set.fb)) + save_set.x, save_set.y, save_set.fb, + state)) DRM_ERROR("failed to restore config after modeset failure\n"); } out_config: + if (state) + drm_atomic_state_free(state); + intel_set_config_free(config); return ret; } @@ -11889,6 +12250,28 @@ static void intel_shared_dpll_init(struct drm_device *dev) BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS); } +/** + * intel_wm_need_update - Check whether watermarks need updating + * @plane: drm plane + * @state: new plane state + * + * Check current plane state versus the new one to determine whether + * watermarks need to be recalculated. + * + * Returns true or false. + */ +bool intel_wm_need_update(struct drm_plane *plane, + struct drm_plane_state *state) +{ + /* Update watermarks on tiling changes. */ + if (!plane->state->fb || !state->fb || + plane->state->fb->modifier[0] != state->fb->modifier[0] || + plane->state->rotation != state->rotation) + return true; + + return false; +} + /** * intel_prepare_plane_fb - Prepare fb for usage on plane * @plane: drm plane to prepare for @@ -11938,7 +12321,7 @@ intel_prepare_plane_fb(struct drm_plane *plane, if (ret) DRM_DEBUG_KMS("failed to attach phys object\n"); } else { - ret = intel_pin_and_fence_fb_obj(plane, fb, NULL); + ret = intel_pin_and_fence_fb_obj(plane, fb, new_state, NULL); } if (ret == 0) @@ -11970,7 +12353,7 @@ intel_cleanup_plane_fb(struct drm_plane *plane, if (plane->type != DRM_PLANE_TYPE_CURSOR || !INTEL_INFO(dev)->cursor_needs_physical) { mutex_lock(&dev->struct_mutex); - intel_unpin_fb_obj(obj); + intel_unpin_fb_obj(fb, old_state); mutex_unlock(&dev->struct_mutex); } } @@ -12035,10 +12418,7 @@ intel_check_primary_plane(struct drm_plane *plane, intel_crtc->atomic.update_fbc = true; - /* Update watermarks on tiling changes. */ - if (!plane->state->fb || !state->base.fb || - plane->state->fb->modifier[0] != - state->base.fb->modifier[0]) + if (intel_wm_need_update(plane, &state->base)) intel_crtc->atomic.update_wm = true; } @@ -12054,8 +12434,6 @@ intel_commit_primary_plane(struct drm_plane *plane, struct drm_device *dev = plane->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc; - struct drm_i915_gem_object *obj = intel_fb_obj(fb); - struct intel_plane *intel_plane = to_intel_plane(plane); struct drm_rect *src = &state->src; crtc = crtc ? crtc : plane->crtc; @@ -12065,8 +12443,6 @@ intel_commit_primary_plane(struct drm_plane *plane, crtc->x = src->x1 >> 16; crtc->y = src->y1 >> 16; - intel_plane->obj = obj; - if (intel_crtc->active) { if (state->visible) { /* FIXME: kill this fastboot hack */ @@ -12313,7 +12689,7 @@ intel_check_cursor_plane(struct drm_plane *plane, finish: if (intel_crtc->active) { - if (intel_crtc->base.cursor->state->crtc_w != state->base.crtc_w) + if (plane->state->crtc_w != state->base.crtc_w) intel_crtc->atomic.update_wm = true; intel_crtc->atomic.fb_bits |= @@ -12330,7 +12706,6 @@ intel_commit_cursor_plane(struct drm_plane *plane, struct drm_crtc *crtc = state->base.crtc; struct drm_device *dev = plane->dev; struct intel_crtc *intel_crtc; - struct intel_plane *intel_plane = to_intel_plane(plane); struct drm_i915_gem_object *obj = intel_fb_obj(state->base.fb); uint32_t addr; @@ -12341,8 +12716,6 @@ intel_commit_cursor_plane(struct drm_plane *plane, crtc->cursor_x = state->base.crtc_x; crtc->cursor_y = state->base.crtc_y; - intel_plane->obj = obj; - if (intel_crtc->cursor_bo == obj) goto update; @@ -12583,10 +12956,15 @@ static void intel_setup_outputs(struct drm_device *dev) if (HAS_DDI(dev)) { int found; - /* Haswell uses DDI functions to detect digital outputs */ + /* + * Haswell uses DDI functions to detect digital outputs. + * On SKL pre-D0 the strap isn't connected, so we assume + * it's there. + */ found = I915_READ(DDI_BUF_CTL_A) & DDI_INIT_DISPLAY_DETECTED; - /* DDI A only supports eDP */ - if (found) + /* WaIgnoreDDIAStrap: skl */ + if (found || + (IS_SKYLAKE(dev) && INTEL_REVID(dev) < SKL_REVID_D0)) intel_ddi_init(dev, PORT_A); /* DDI B, C and D detection is indicated by the SFUSE_STRAP @@ -12718,19 +13096,21 @@ static void intel_setup_outputs(struct drm_device *dev) * testing/debug of the plane operations (and only when a specific * kernel module option is given), that shouldn't really matter. * + * We are also relying on these states to convert the legacy mode set + * to use a drm_atomic_state struct. The states are kept consistent + * with actual state, so that it is safe to rely on that instead of + * the staged config. + * * Once atomic support for crtc's + connectors lands, this loop should * be removed since we'll be setting up real connector state, which * will contain Intel-specific properties. */ - if (drm_core_check_feature(dev, DRIVER_ATOMIC)) { - list_for_each_entry(connector, - &dev->mode_config.connector_list, - head) { - if (!WARN_ON(connector->state)) { - connector->state = - kzalloc(sizeof(*connector->state), - GFP_KERNEL); - } + list_for_each_entry(connector, + &dev->mode_config.connector_list, + head) { + if (!WARN_ON(connector->state)) { + connector->state = kzalloc(sizeof(*connector->state), + GFP_KERNEL); } } @@ -12809,7 +13189,7 @@ static int intel_framebuffer_init(struct drm_device *dev, struct drm_mode_fb_cmd2 *mode_cmd, struct drm_i915_gem_object *obj) { - int aligned_height; + unsigned int aligned_height; int ret; u32 pitch_limit, stride_alignment; @@ -12845,8 +13225,8 @@ static int intel_framebuffer_init(struct drm_device *dev, case I915_FORMAT_MOD_X_TILED: break; default: - DRM_ERROR("Unsupported fb modifier 0x%llx!\n", - mode_cmd->modifier[0]); + DRM_DEBUG("Unsupported fb modifier 0x%llx!\n", + mode_cmd->modifier[0]); return -EINVAL; } @@ -13077,8 +13457,6 @@ static void intel_init_display(struct drm_device *dev) } else if (IS_IVYBRIDGE(dev)) { /* FIXME: detect B0+ stepping and use auto training */ dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train; - dev_priv->display.modeset_global_resources = - ivb_modeset_global_resources; } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { dev_priv->display.fdi_link_train = hsw_fdi_link_train; } else if (IS_VALLEYVIEW(dev)) { @@ -13415,7 +13793,7 @@ void intel_modeset_init(struct drm_device *dev) * If the fb is shared between multiple heads, we'll * just get the first one. */ - intel_find_plane_obj(crtc, &crtc->plane_config); + intel_find_initial_plane_obj(crtc, &crtc->plane_config); } } } @@ -13441,7 +13819,7 @@ static void intel_enable_pipe_a(struct drm_device *dev) return; if (intel_get_load_detect_pipe(crt, NULL, &load_detect_temp, ctx)) - intel_release_load_detect_pipe(crt, &load_detect_temp); + intel_release_load_detect_pipe(crt, &load_detect_temp, ctx); } static bool @@ -13785,6 +14163,8 @@ void intel_modeset_setup_hw_state(struct drm_device *dev, "[setup_hw_state]"); } + intel_modeset_update_connector_atomic_state(dev); + for (i = 0; i < dev_priv->num_shared_dpll; i++) { struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i]; @@ -13813,8 +14193,7 @@ 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_crtc_restore_mode(crtc); } } else { intel_modeset_update_staged_output_state(dev); @@ -13860,6 +14239,7 @@ void intel_modeset_gem_init(struct drm_device *dev) if (intel_pin_and_fence_fb_obj(c->primary, c->primary->fb, + c->primary->state, NULL)) { DRM_ERROR("failed to pin boot fb on pipe %d\n", to_intel_crtc(c)->pipe); @@ -13909,8 +14289,6 @@ void intel_modeset_cleanup(struct drm_device *dev) intel_fbc_disable(dev); - ironlake_teardown_rc6(dev); - mutex_unlock(&dev->struct_mutex); /* flush any delayed tasks or pending work */