diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/i9xx_plane.c')
-rw-r--r-- | drivers/gpu/drm/i915/display/i9xx_plane.c | 373 |
1 files changed, 221 insertions, 152 deletions
diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c index 17a1e3801a85..013295f66d56 100644 --- a/drivers/gpu/drm/i915/display/i9xx_plane.c +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c @@ -8,6 +8,7 @@ #include <drm/drm_blend.h> #include <drm/drm_fourcc.h> +#include "i915_drv.h" #include "i915_reg.h" #include "i9xx_plane.h" #include "i9xx_plane_regs.h" @@ -108,42 +109,42 @@ static bool i965_plane_format_mod_supported(struct drm_plane *_plane, } } -static bool i9xx_plane_has_fbc(struct drm_i915_private *dev_priv, +static bool i9xx_plane_has_fbc(struct intel_display *display, enum i9xx_plane_id i9xx_plane) { - if (!HAS_FBC(dev_priv)) + if (!HAS_FBC(display)) return false; - if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) + if (display->platform.broadwell || display->platform.haswell) return i9xx_plane == PLANE_A; /* tied to pipe A */ - else if (IS_IVYBRIDGE(dev_priv)) + else if (display->platform.ivybridge) return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B || i9xx_plane == PLANE_C; - else if (DISPLAY_VER(dev_priv) >= 4) + else if (DISPLAY_VER(display) >= 4) return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B; else return i9xx_plane == PLANE_A; } -static struct intel_fbc *i9xx_plane_fbc(struct drm_i915_private *dev_priv, +static struct intel_fbc *i9xx_plane_fbc(struct intel_display *display, enum i9xx_plane_id i9xx_plane) { - if (i9xx_plane_has_fbc(dev_priv, i9xx_plane)) - return dev_priv->display.fbc[INTEL_FBC_A]; + if (i9xx_plane_has_fbc(display, i9xx_plane)) + return display->fbc[INTEL_FBC_A]; else return NULL; } static bool i9xx_plane_has_windowing(struct intel_plane *plane) { - struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + struct intel_display *display = to_intel_display(plane); enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; - if (IS_CHERRYVIEW(dev_priv)) + if (display->platform.cherryview) return i9xx_plane == PLANE_B; - else if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv)) + else if (DISPLAY_VER(display) >= 5 || display->platform.g4x) return false; - else if (DISPLAY_VER(dev_priv) == 4) + else if (DISPLAY_VER(display) == 4) return i9xx_plane == PLANE_C; else return i9xx_plane == PLANE_B || @@ -153,16 +154,15 @@ static bool i9xx_plane_has_windowing(struct intel_plane *plane) static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { - struct drm_i915_private *dev_priv = - to_i915(plane_state->uapi.plane->dev); + struct intel_display *display = to_intel_display(plane_state); const struct drm_framebuffer *fb = plane_state->hw.fb; unsigned int rotation = plane_state->hw.rotation; u32 dspcntr; dspcntr = DISP_ENABLE; - if (IS_G4X(dev_priv) || IS_IRONLAKE(dev_priv) || - IS_SANDYBRIDGE(dev_priv) || IS_IVYBRIDGE(dev_priv)) + if (display->platform.g4x || display->platform.ironlake || + display->platform.sandybridge || display->platform.ivybridge) dspcntr |= DISP_TRICKLE_FEED_DISABLE; switch (fb->format->format) { @@ -210,7 +210,7 @@ static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state, return 0; } - if (DISPLAY_VER(dev_priv) >= 4 && + if (DISPLAY_VER(display) >= 4 && fb->modifier == I915_FORMAT_MOD_X_TILED) dspcntr |= DISP_TILED; @@ -225,8 +225,8 @@ static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state, int i9xx_check_plane_surface(struct intel_plane_state *plane_state) { + struct intel_display *display = to_intel_display(plane_state); struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); - struct drm_i915_private *dev_priv = to_i915(plane->base.dev); const struct drm_framebuffer *fb = plane_state->hw.fb; int src_x, src_y, src_w; u32 offset; @@ -244,12 +244,16 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state) src_y = plane_state->uapi.src.y1 >> 16; /* Undocumented hardware limit on i965/g4x/vlv/chv */ - if (HAS_GMCH(dev_priv) && fb->format->cpp[0] == 8 && src_w > 2048) + if (HAS_GMCH(display) && fb->format->cpp[0] == 8 && src_w > 2048) { + drm_dbg_kms(display->drm, + "[PLANE:%d:%s] plane too wide (%d) for 64bpp\n", + plane->base.base.id, plane->base.name, src_w); return -EINVAL; + } intel_add_fb_offsets(&src_x, &src_y, plane_state, 0); - if (DISPLAY_VER(dev_priv) >= 4) + if (DISPLAY_VER(display) >= 4) offset = intel_plane_compute_aligned_offset(&src_x, &src_y, plane_state, 0); else @@ -266,14 +270,15 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state) * Linear surfaces seem to work just fine, even on hsw/bdw * despite them not using the linear offset anymore. */ - if (DISPLAY_VER(dev_priv) >= 4 && fb->modifier == I915_FORMAT_MOD_X_TILED) { + if (DISPLAY_VER(display) >= 4 && fb->modifier == I915_FORMAT_MOD_X_TILED) { unsigned int alignment = plane->min_alignment(plane, fb, 0); int cpp = fb->format->cpp[0]; while ((src_x + src_w) * cpp > plane_state->view.color_plane[0].mapping_stride) { if (offset == 0) { - drm_dbg_kms(&dev_priv->drm, - "Unable to find suitable display surface offset due to X-tiling\n"); + drm_dbg_kms(display->drm, + "[PLANE:%d:%s] unable to find suitable display surface offset due to X-tiling\n", + plane->base.base.id, plane->base.name); return -EINVAL; } @@ -290,7 +295,7 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state) src_x << 16, src_y << 16); /* HSW/BDW do this automagically in hardware */ - if (!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)) { + if (!display->platform.haswell && !display->platform.broadwell) { unsigned int rotation = plane_state->hw.rotation; int src_w = drm_rect_width(&plane_state->uapi.src) >> 16; int src_h = drm_rect_height(&plane_state->uapi.src) >> 16; @@ -303,11 +308,11 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state) } } - if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { - drm_WARN_ON(&dev_priv->drm, src_x > 8191 || src_y > 4095); - } else if (DISPLAY_VER(dev_priv) >= 4 && + if (display->platform.haswell || display->platform.broadwell) { + drm_WARN_ON(display->drm, src_x > 8191 || src_y > 4095); + } else if (DISPLAY_VER(display) >= 4 && fb->modifier == I915_FORMAT_MOD_X_TILED) { - drm_WARN_ON(&dev_priv->drm, src_x > 4095 || src_y > 4095); + drm_WARN_ON(display->drm, src_x > 4095 || src_y > 4095); } plane_state->view.color_plane[0].offset = offset; @@ -353,8 +358,8 @@ i9xx_plane_check(struct intel_crtc_state *crtc_state, static u32 i9xx_plane_ctl_crtc(const struct intel_crtc_state *crtc_state) { + struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 dspcntr = 0; if (crtc_state->gamma_enable) @@ -363,7 +368,7 @@ static u32 i9xx_plane_ctl_crtc(const struct intel_crtc_state *crtc_state) if (crtc_state->csc_enable) dspcntr |= DISP_PIPE_CSC_ENABLE; - if (DISPLAY_VER(dev_priv) < 5) + if (DISPLAY_VER(display) < 5) dspcntr |= DISP_PIPE_SEL(crtc->pipe); return dspcntr; @@ -421,13 +426,13 @@ static void i9xx_plane_update_noarm(struct intel_dsb *dsb, const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { - struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + struct intel_display *display = to_intel_display(plane); enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; - intel_de_write_fw(dev_priv, DSPSTRIDE(dev_priv, i9xx_plane), + intel_de_write_fw(display, DSPSTRIDE(display, i9xx_plane), plane_state->view.color_plane[0].mapping_stride); - if (DISPLAY_VER(dev_priv) < 4) { + if (DISPLAY_VER(display) < 4) { int crtc_x = plane_state->uapi.dst.x1; int crtc_y = plane_state->uapi.dst.y1; int crtc_w = drm_rect_width(&plane_state->uapi.dst); @@ -438,9 +443,9 @@ static void i9xx_plane_update_noarm(struct intel_dsb *dsb, * generator but let's assume we still need to * program whatever is there. */ - intel_de_write_fw(dev_priv, DSPPOS(dev_priv, i9xx_plane), + intel_de_write_fw(display, DSPPOS(display, i9xx_plane), DISP_POS_Y(crtc_y) | DISP_POS_X(crtc_x)); - intel_de_write_fw(dev_priv, DSPSIZE(dev_priv, i9xx_plane), + intel_de_write_fw(display, DSPSIZE(display, i9xx_plane), DISP_HEIGHT(crtc_h - 1) | DISP_WIDTH(crtc_w - 1)); } } @@ -450,7 +455,7 @@ static void i9xx_plane_update_arm(struct intel_dsb *dsb, const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { - struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + struct intel_display *display = to_intel_display(plane); enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; int x = plane_state->view.color_plane[0].x; int y = plane_state->view.color_plane[0].y; @@ -465,32 +470,32 @@ static void i9xx_plane_update_arm(struct intel_dsb *dsb, linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); - if (DISPLAY_VER(dev_priv) >= 4) + if (DISPLAY_VER(display) >= 4) dspaddr_offset = plane_state->view.color_plane[0].offset; else dspaddr_offset = linear_offset; - if (IS_CHERRYVIEW(dev_priv) && i9xx_plane == PLANE_B) { + if (display->platform.cherryview && i9xx_plane == PLANE_B) { int crtc_x = plane_state->uapi.dst.x1; int crtc_y = plane_state->uapi.dst.y1; int crtc_w = drm_rect_width(&plane_state->uapi.dst); int crtc_h = drm_rect_height(&plane_state->uapi.dst); - intel_de_write_fw(dev_priv, PRIMPOS(dev_priv, i9xx_plane), + intel_de_write_fw(display, PRIMPOS(display, i9xx_plane), PRIM_POS_Y(crtc_y) | PRIM_POS_X(crtc_x)); - intel_de_write_fw(dev_priv, PRIMSIZE(dev_priv, i9xx_plane), + intel_de_write_fw(display, PRIMSIZE(display, i9xx_plane), PRIM_HEIGHT(crtc_h - 1) | PRIM_WIDTH(crtc_w - 1)); - intel_de_write_fw(dev_priv, - PRIMCNSTALPHA(dev_priv, i9xx_plane), 0); + intel_de_write_fw(display, + PRIMCNSTALPHA(display, i9xx_plane), 0); } - if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { - intel_de_write_fw(dev_priv, DSPOFFSET(dev_priv, i9xx_plane), + if (display->platform.haswell || display->platform.broadwell) { + intel_de_write_fw(display, DSPOFFSET(display, i9xx_plane), DISP_OFFSET_Y(y) | DISP_OFFSET_X(x)); - } else if (DISPLAY_VER(dev_priv) >= 4) { - intel_de_write_fw(dev_priv, DSPLINOFF(dev_priv, i9xx_plane), + } else if (DISPLAY_VER(display) >= 4) { + intel_de_write_fw(display, DSPLINOFF(display, i9xx_plane), linear_offset); - intel_de_write_fw(dev_priv, DSPTILEOFF(dev_priv, i9xx_plane), + intel_de_write_fw(display, DSPTILEOFF(display, i9xx_plane), DISP_OFFSET_Y(y) | DISP_OFFSET_X(x)); } @@ -499,13 +504,13 @@ static void i9xx_plane_update_arm(struct intel_dsb *dsb, * disabled. Try to make the plane enable atomic by writing * the control register just before the surface register. */ - intel_de_write_fw(dev_priv, DSPCNTR(dev_priv, i9xx_plane), dspcntr); + intel_de_write_fw(display, DSPCNTR(display, i9xx_plane), dspcntr); - if (DISPLAY_VER(dev_priv) >= 4) - intel_de_write_fw(dev_priv, DSPSURF(dev_priv, i9xx_plane), + if (DISPLAY_VER(display) >= 4) + intel_de_write_fw(display, DSPSURF(display, i9xx_plane), intel_plane_ggtt_offset(plane_state) + dspaddr_offset); else - intel_de_write_fw(dev_priv, DSPADDR(dev_priv, i9xx_plane), + intel_de_write_fw(display, DSPADDR(display, i9xx_plane), intel_plane_ggtt_offset(plane_state) + dspaddr_offset); } @@ -528,7 +533,7 @@ static void i9xx_plane_disable_arm(struct intel_dsb *dsb, struct intel_plane *plane, const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + struct intel_display *display = to_intel_display(plane); enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; u32 dspcntr; @@ -544,12 +549,46 @@ static void i9xx_plane_disable_arm(struct intel_dsb *dsb, */ dspcntr = i9xx_plane_ctl_crtc(crtc_state); - intel_de_write_fw(dev_priv, DSPCNTR(dev_priv, i9xx_plane), dspcntr); + intel_de_write_fw(display, DSPCNTR(display, i9xx_plane), dspcntr); - if (DISPLAY_VER(dev_priv) >= 4) - intel_de_write_fw(dev_priv, DSPSURF(dev_priv, i9xx_plane), 0); + if (DISPLAY_VER(display) >= 4) + intel_de_write_fw(display, DSPSURF(display, i9xx_plane), 0); else - intel_de_write_fw(dev_priv, DSPADDR(dev_priv, i9xx_plane), 0); + intel_de_write_fw(display, DSPADDR(display, i9xx_plane), 0); +} + +static void g4x_primary_capture_error(struct intel_crtc *crtc, + struct intel_plane *plane, + struct intel_plane_error *error) +{ + struct intel_display *display = to_intel_display(plane); + enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; + + error->ctl = intel_de_read(display, DSPCNTR(display, i9xx_plane)); + error->surf = intel_de_read(display, DSPSURF(display, i9xx_plane)); + error->surflive = intel_de_read(display, DSPSURFLIVE(display, i9xx_plane)); +} + +static void i965_plane_capture_error(struct intel_crtc *crtc, + struct intel_plane *plane, + struct intel_plane_error *error) +{ + struct intel_display *display = to_intel_display(plane); + enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; + + error->ctl = intel_de_read(display, DSPCNTR(display, i9xx_plane)); + error->surf = intel_de_read(display, DSPSURF(display, i9xx_plane)); +} + +static void i8xx_plane_capture_error(struct intel_crtc *crtc, + struct intel_plane *plane, + struct intel_plane_error *error) +{ + struct intel_display *display = to_intel_display(plane); + enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; + + error->ctl = intel_de_read(display, DSPCNTR(display, i9xx_plane)); + error->surf = intel_de_read(display, DSPADDR(display, i9xx_plane)); } static void @@ -559,7 +598,7 @@ g4x_primary_async_flip(struct intel_dsb *dsb, const struct intel_plane_state *plane_state, bool async_flip) { - struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + struct intel_display *display = to_intel_display(plane); u32 dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state); u32 dspaddr_offset = plane_state->view.color_plane[0].offset; enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; @@ -567,9 +606,9 @@ g4x_primary_async_flip(struct intel_dsb *dsb, if (async_flip) dspcntr |= DISP_ASYNC_FLIP; - intel_de_write_fw(dev_priv, DSPCNTR(dev_priv, i9xx_plane), dspcntr); + intel_de_write_fw(display, DSPCNTR(display, i9xx_plane), dspcntr); - intel_de_write_fw(dev_priv, DSPSURF(dev_priv, i9xx_plane), + intel_de_write_fw(display, DSPSURF(display, i9xx_plane), intel_plane_ggtt_offset(plane_state) + dspaddr_offset); } @@ -580,11 +619,11 @@ vlv_primary_async_flip(struct intel_dsb *dsb, const struct intel_plane_state *plane_state, bool async_flip) { - struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + struct intel_display *display = to_intel_display(plane); u32 dspaddr_offset = plane_state->view.color_plane[0].offset; enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; - intel_de_write_fw(dev_priv, DSPADDR_VLV(dev_priv, i9xx_plane), + intel_de_write_fw(display, DSPADDR_VLV(display, i9xx_plane), intel_plane_ggtt_offset(plane_state) + dspaddr_offset); } @@ -672,10 +711,15 @@ vlv_primary_disable_flip_done(struct intel_plane *plane) spin_unlock_irq(&i915->irq_lock); } +static bool i9xx_plane_can_async_flip(u64 modifier) +{ + return modifier == I915_FORMAT_MOD_X_TILED; +} + static bool i9xx_plane_get_hw_state(struct intel_plane *plane, enum pipe *pipe) { - struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + struct intel_display *display = to_intel_display(plane); enum intel_display_power_domain power_domain; enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; intel_wakeref_t wakeref; @@ -688,20 +732,20 @@ static bool i9xx_plane_get_hw_state(struct intel_plane *plane, * display power wells. */ power_domain = POWER_DOMAIN_PIPE(plane->pipe); - wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain); + wakeref = intel_display_power_get_if_enabled(display, power_domain); if (!wakeref) return false; - val = intel_de_read(dev_priv, DSPCNTR(dev_priv, i9xx_plane)); + val = intel_de_read(display, DSPCNTR(display, i9xx_plane)); ret = val & DISP_ENABLE; - if (DISPLAY_VER(dev_priv) >= 5) + if (DISPLAY_VER(display) >= 5) *pipe = plane->pipe; else *pipe = REG_FIELD_GET(DISP_PIPE_SEL_MASK, val); - intel_display_power_put(dev_priv, power_domain, wakeref); + intel_display_power_put(display, power_domain, wakeref); return ret; } @@ -770,16 +814,21 @@ i8xx_plane_max_stride(struct intel_plane *plane, return 8 * 1024; } -static unsigned int vlv_primary_min_alignment(struct intel_plane *plane, - const struct drm_framebuffer *fb, - int color_plane) +unsigned int vlv_plane_min_alignment(struct intel_plane *plane, + const struct drm_framebuffer *fb, + int color_plane) { - struct drm_i915_private *i915 = to_i915(plane->base.dev); + struct intel_display *display = to_intel_display(plane); + + if (intel_plane_can_async_flip(plane, fb->modifier)) + return 256 * 1024; + + /* FIXME undocumented so not sure what's actually needed */ + if (intel_scanout_needs_vtd_wa(display)) + return 256 * 1024; switch (fb->modifier) { case I915_FORMAT_MOD_X_TILED: - if (HAS_ASYNC_FLIPS(i915)) - return 256 * 1024; return 4 * 1024; case DRM_FORMAT_MOD_LINEAR: return 128 * 1024; @@ -793,13 +842,16 @@ static unsigned int g4x_primary_min_alignment(struct intel_plane *plane, const struct drm_framebuffer *fb, int color_plane) { - struct drm_i915_private *i915 = to_i915(plane->base.dev); + struct intel_display *display = to_intel_display(plane); + + if (intel_plane_can_async_flip(plane, fb->modifier)) + return 256 * 1024; + + if (intel_scanout_needs_vtd_wa(display)) + return 256 * 1024; switch (fb->modifier) { case I915_FORMAT_MOD_X_TILED: - if (HAS_ASYNC_FLIPS(i915)) - return 256 * 1024; - return 4 * 1024; case DRM_FORMAT_MOD_LINEAR: return 4 * 1024; default: @@ -849,7 +901,7 @@ static const struct drm_plane_funcs i8xx_plane_funcs = { }; struct intel_plane * -intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) +intel_primary_plane_create(struct intel_display *display, enum pipe pipe) { struct intel_plane *plane; const struct drm_plane_funcs *plane_funcs; @@ -868,20 +920,20 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) * On gen2/3 only plane A can do FBC, but the panel fitter and LVDS * port is hooked to pipe B. Hence we want plane A feeding pipe B. */ - if (HAS_FBC(dev_priv) && DISPLAY_VER(dev_priv) < 4 && - INTEL_NUM_PIPES(dev_priv) == 2) + if (HAS_FBC(display) && DISPLAY_VER(display) < 4 && + INTEL_NUM_PIPES(display) == 2) plane->i9xx_plane = (enum i9xx_plane_id) !pipe; else plane->i9xx_plane = (enum i9xx_plane_id) pipe; plane->id = PLANE_PRIMARY; plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id); - intel_fbc_add_plane(i9xx_plane_fbc(dev_priv, plane->i9xx_plane), plane); + intel_fbc_add_plane(i9xx_plane_fbc(display, plane->i9xx_plane), plane); - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { + if (display->platform.valleyview || display->platform.cherryview) { formats = vlv_primary_formats; num_formats = ARRAY_SIZE(vlv_primary_formats); - } else if (DISPLAY_VER(dev_priv) >= 4) { + } else if (DISPLAY_VER(display) >= 4) { /* * WaFP16GammaEnabling:ivb * "Workaround : When using the 64-bit format, the plane @@ -895,7 +947,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) * planes, so we choose not to expose fp16 on IVB primary * planes. HSW primary planes no longer have this problem. */ - if (IS_IVYBRIDGE(dev_priv)) { + if (display->platform.ivybridge) { formats = ivb_primary_formats; num_formats = ARRAY_SIZE(ivb_primary_formats); } else { @@ -907,44 +959,48 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) num_formats = ARRAY_SIZE(i8xx_primary_formats); } - if (DISPLAY_VER(dev_priv) >= 4) + if (DISPLAY_VER(display) >= 4) plane_funcs = &i965_plane_funcs; else plane_funcs = &i8xx_plane_funcs; - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) + if (display->platform.valleyview || display->platform.cherryview) plane->min_cdclk = vlv_plane_min_cdclk; - else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) + else if (display->platform.broadwell || display->platform.haswell) plane->min_cdclk = hsw_plane_min_cdclk; - else if (IS_IVYBRIDGE(dev_priv)) + else if (display->platform.ivybridge) plane->min_cdclk = ivb_plane_min_cdclk; else plane->min_cdclk = i9xx_plane_min_cdclk; - if (HAS_GMCH(dev_priv)) { - if (DISPLAY_VER(dev_priv) >= 4) + if (HAS_GMCH(display)) { + if (DISPLAY_VER(display) >= 4) plane->max_stride = i965_plane_max_stride; - else if (DISPLAY_VER(dev_priv) == 3) + else if (DISPLAY_VER(display) == 3) plane->max_stride = i915_plane_max_stride; else plane->max_stride = i8xx_plane_max_stride; } else { - if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) + if (display->platform.broadwell || display->platform.haswell) plane->max_stride = hsw_primary_max_stride; else plane->max_stride = ilk_primary_max_stride; } - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) - plane->min_alignment = vlv_primary_min_alignment; - else if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv)) + if (display->platform.valleyview || display->platform.cherryview) + plane->min_alignment = vlv_plane_min_alignment; + else if (DISPLAY_VER(display) >= 5 || display->platform.g4x) plane->min_alignment = g4x_primary_min_alignment; - else if (DISPLAY_VER(dev_priv) == 4) + else if (DISPLAY_VER(display) == 4) plane->min_alignment = i965_plane_min_alignment; else plane->min_alignment = i9xx_plane_min_alignment; - if (IS_I830(dev_priv) || IS_I845G(dev_priv)) { + /* FIXME undocumented for VLV/CHV so not sure what's actually needed */ + if (intel_scanout_needs_vtd_wa(display)) + plane->vtd_guard = 128; + + if (display->platform.i830 || display->platform.i845g) { plane->update_arm = i830_plane_update_arm; } else { plane->update_noarm = i9xx_plane_update_noarm; @@ -954,36 +1010,49 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) plane->get_hw_state = i9xx_plane_get_hw_state; plane->check_plane = i9xx_plane_check; - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { - plane->async_flip = vlv_primary_async_flip; - plane->enable_flip_done = vlv_primary_enable_flip_done; - plane->disable_flip_done = vlv_primary_disable_flip_done; - } else if (IS_BROADWELL(dev_priv)) { - plane->need_async_flip_toggle_wa = true; - plane->async_flip = g4x_primary_async_flip; - plane->enable_flip_done = bdw_primary_enable_flip_done; - plane->disable_flip_done = bdw_primary_disable_flip_done; - } else if (DISPLAY_VER(dev_priv) >= 7) { - plane->async_flip = g4x_primary_async_flip; - plane->enable_flip_done = ivb_primary_enable_flip_done; - plane->disable_flip_done = ivb_primary_disable_flip_done; - } else if (DISPLAY_VER(dev_priv) >= 5) { - plane->async_flip = g4x_primary_async_flip; - plane->enable_flip_done = ilk_primary_enable_flip_done; - plane->disable_flip_done = ilk_primary_disable_flip_done; + if (DISPLAY_VER(display) >= 5 || display->platform.g4x) + plane->capture_error = g4x_primary_capture_error; + else if (DISPLAY_VER(display) >= 4) + plane->capture_error = i965_plane_capture_error; + else + plane->capture_error = i8xx_plane_capture_error; + + if (HAS_ASYNC_FLIPS(display)) { + if (display->platform.valleyview || display->platform.cherryview) { + plane->async_flip = vlv_primary_async_flip; + plane->enable_flip_done = vlv_primary_enable_flip_done; + plane->disable_flip_done = vlv_primary_disable_flip_done; + plane->can_async_flip = i9xx_plane_can_async_flip; + } else if (display->platform.broadwell) { + plane->need_async_flip_toggle_wa = true; + plane->async_flip = g4x_primary_async_flip; + plane->enable_flip_done = bdw_primary_enable_flip_done; + plane->disable_flip_done = bdw_primary_disable_flip_done; + plane->can_async_flip = i9xx_plane_can_async_flip; + } else if (DISPLAY_VER(display) >= 7) { + plane->async_flip = g4x_primary_async_flip; + plane->enable_flip_done = ivb_primary_enable_flip_done; + plane->disable_flip_done = ivb_primary_disable_flip_done; + plane->can_async_flip = i9xx_plane_can_async_flip; + } else if (DISPLAY_VER(display) >= 5) { + plane->async_flip = g4x_primary_async_flip; + plane->enable_flip_done = ilk_primary_enable_flip_done; + plane->disable_flip_done = ilk_primary_disable_flip_done; + plane->can_async_flip = i9xx_plane_can_async_flip; + } } - modifiers = intel_fb_plane_get_modifiers(dev_priv, INTEL_PLANE_CAP_TILING_X); + modifiers = intel_fb_plane_get_modifiers(display, INTEL_PLANE_CAP_TILING_X); - if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv)) - ret = drm_universal_plane_init(&dev_priv->drm, &plane->base, + if (DISPLAY_VER(display) >= 5 || display->platform.g4x) + ret = drm_universal_plane_init(display->drm, &plane->base, 0, plane_funcs, formats, num_formats, modifiers, DRM_PLANE_TYPE_PRIMARY, "primary %c", pipe_name(pipe)); else - ret = drm_universal_plane_init(&dev_priv->drm, &plane->base, + ret = drm_universal_plane_init(display->drm, &plane->base, 0, plane_funcs, formats, num_formats, modifiers, @@ -996,18 +1065,18 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) if (ret) goto fail; - if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) { + if (display->platform.cherryview && pipe == PIPE_B) { supported_rotations = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 | DRM_MODE_REFLECT_X; - } else if (DISPLAY_VER(dev_priv) >= 4) { + } else if (DISPLAY_VER(display) >= 4) { supported_rotations = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180; } else { supported_rotations = DRM_MODE_ROTATE_0; } - if (DISPLAY_VER(dev_priv) >= 4) + if (DISPLAY_VER(display) >= 4) drm_plane_create_rotation_property(&plane->base, DRM_MODE_ROTATE_0, supported_rotations); @@ -1062,8 +1131,7 @@ void i9xx_get_initial_plane_config(struct intel_crtc *crtc, struct intel_initial_plane_config *plane_config) { - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_display *display = to_intel_display(crtc); struct intel_plane *plane = to_intel_plane(crtc->base.primary); enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; enum pipe pipe; @@ -1076,21 +1144,21 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc, if (!plane->get_hw_state(plane, &pipe)) return; - drm_WARN_ON(dev, pipe != crtc->pipe); + drm_WARN_ON(display->drm, pipe != crtc->pipe); intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); if (!intel_fb) { - drm_dbg_kms(&dev_priv->drm, "failed to alloc fb\n"); + drm_dbg_kms(display->drm, "failed to alloc fb\n"); return; } fb = &intel_fb->base; - fb->dev = dev; + fb->dev = display->drm; - val = intel_de_read(dev_priv, DSPCNTR(dev_priv, i9xx_plane)); + val = intel_de_read(display, DSPCNTR(display, i9xx_plane)); - if (DISPLAY_VER(dev_priv) >= 4) { + if (DISPLAY_VER(display) >= 4) { if (val & DISP_TILED) { plane_config->tiling = I915_TILING_X; fb->modifier = I915_FORMAT_MOD_X_TILED; @@ -1100,50 +1168,51 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc, plane_config->rotation = DRM_MODE_ROTATE_180; } - if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B && - val & DISP_MIRROR) + if (display->platform.cherryview && + pipe == PIPE_B && val & DISP_MIRROR) plane_config->rotation |= DRM_MODE_REFLECT_X; pixel_format = val & DISP_FORMAT_MASK; fourcc = i9xx_format_to_fourcc(pixel_format); fb->format = drm_format_info(fourcc); - if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { - offset = intel_de_read(dev_priv, - DSPOFFSET(dev_priv, i9xx_plane)); - base = intel_de_read(dev_priv, DSPSURF(dev_priv, i9xx_plane)) & DISP_ADDR_MASK; - } else if (DISPLAY_VER(dev_priv) >= 4) { + if (display->platform.haswell || display->platform.broadwell) { + offset = intel_de_read(display, + DSPOFFSET(display, i9xx_plane)); + base = intel_de_read(display, DSPSURF(display, i9xx_plane)) & DISP_ADDR_MASK; + } else if (DISPLAY_VER(display) >= 4) { if (plane_config->tiling) - offset = intel_de_read(dev_priv, - DSPTILEOFF(dev_priv, i9xx_plane)); + offset = intel_de_read(display, + DSPTILEOFF(display, i9xx_plane)); else - offset = intel_de_read(dev_priv, - DSPLINOFF(dev_priv, i9xx_plane)); - base = intel_de_read(dev_priv, DSPSURF(dev_priv, i9xx_plane)) & DISP_ADDR_MASK; + offset = intel_de_read(display, + DSPLINOFF(display, i9xx_plane)); + base = intel_de_read(display, DSPSURF(display, i9xx_plane)) & DISP_ADDR_MASK; } else { offset = 0; - base = intel_de_read(dev_priv, DSPADDR(dev_priv, i9xx_plane)); + base = intel_de_read(display, DSPADDR(display, i9xx_plane)); } plane_config->base = base; - drm_WARN_ON(&dev_priv->drm, offset != 0); + drm_WARN_ON(display->drm, offset != 0); - val = intel_de_read(dev_priv, PIPESRC(dev_priv, pipe)); + val = intel_de_read(display, PIPESRC(display, pipe)); fb->width = REG_FIELD_GET(PIPESRC_WIDTH_MASK, val) + 1; fb->height = REG_FIELD_GET(PIPESRC_HEIGHT_MASK, val) + 1; - val = intel_de_read(dev_priv, DSPSTRIDE(dev_priv, i9xx_plane)); + val = intel_de_read(display, DSPSTRIDE(display, i9xx_plane)); fb->pitches[0] = val & 0xffffffc0; aligned_height = intel_fb_align_height(fb, 0, fb->height); plane_config->size = fb->pitches[0] * aligned_height; - drm_dbg_kms(&dev_priv->drm, - "%s/%s with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n", - crtc->base.name, plane->base.name, fb->width, fb->height, - fb->format->cpp[0] * 8, base, fb->pitches[0], - plane_config->size); + drm_dbg_kms(display->drm, + "[CRTC:%d:%s][PLANE:%d:%s] with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n", + crtc->base.base.id, crtc->base.name, + plane->base.base.id, plane->base.name, + fb->width, fb->height, fb->format->cpp[0] * 8, + base, fb->pitches[0], plane_config->size); plane_config->fb = intel_fb; } @@ -1151,7 +1220,7 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc, bool i9xx_fixup_initial_plane_config(struct intel_crtc *crtc, const struct intel_initial_plane_config *plane_config) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct intel_display *display = to_intel_display(crtc); struct intel_plane *plane = to_intel_plane(crtc->base.primary); const struct intel_plane_state *plane_state = to_intel_plane_state(plane->base.state); @@ -1170,10 +1239,10 @@ bool i9xx_fixup_initial_plane_config(struct intel_crtc *crtc, if (plane_config->base == base) return false; - if (DISPLAY_VER(dev_priv) >= 4) - intel_de_write(dev_priv, DSPSURF(dev_priv, i9xx_plane), base); + if (DISPLAY_VER(display) >= 4) + intel_de_write(display, DSPSURF(display, i9xx_plane), base); else - intel_de_write(dev_priv, DSPADDR(dev_priv, i9xx_plane), base); + intel_de_write(display, DSPADDR(display, i9xx_plane), base); return true; } |