Message ID | 20201210041755.29088-6-airlied@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [1/9] drm/i915/display: move needs_modeset to an inline in header | expand |
On Thu, Dec 10, 2020 at 02:17:51PM +1000, Dave Airlie wrote: > From: Dave Airlie <airlied@redhat.com> > > There may be more crtc code that can be pulled out, but this > is a good start. a> > RFC: maybe call the new file something different Most of that seems to be the primary plane code. What I would so is: * i9xx_plane.c for all pre-skl plane code * skl_universal_plane.c for the skl+ plane code * non-platform specific plane code probably should go to intel_atomic_plane.c which could perhaps use a rename to just intel_plane.c > > Signed-off-by: Dave Airlie <airlied@redhat.com> > --- > drivers/gpu/drm/i915/Makefile | 1 + > drivers/gpu/drm/i915/display/intel_crtc.c | 951 +++++++++++++++++++ > drivers/gpu/drm/i915/display/intel_display.c | 932 ------------------ > drivers/gpu/drm/i915/display/intel_display.h | 7 + > 4 files changed, 959 insertions(+), 932 deletions(-) > create mode 100644 drivers/gpu/drm/i915/display/intel_crtc.c > > diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile > index 98a35b939052..ffec257702af 100644 > --- a/drivers/gpu/drm/i915/Makefile > +++ b/drivers/gpu/drm/i915/Makefile > @@ -196,6 +196,7 @@ i915-y += \ > display/intel_color.o \ > display/intel_combo_phy.o \ > display/intel_connector.o \ > + display/intel_crtc.o \ > display/intel_csr.o \ > display/intel_cursor.o \ > display/intel_display.o \ > diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c > new file mode 100644 > index 000000000000..75a79f18cee2 > --- /dev/null > +++ b/drivers/gpu/drm/i915/display/intel_crtc.c > @@ -0,0 +1,951 @@ > +// SPDX-License-Identifier: MIT > +/* > + * Copyright © 2020 Intel Corporation > + */ > +#include <linux/kernel.h> > +#include <linux/slab.h> > + > +#include <drm/drm_atomic_helper.h> > +#include <drm/drm_fourcc.h> > +#include <drm/drm_plane.h> > +#include <drm/drm_plane_helper.h> > + > +#include "intel_atomic.h" > +#include "intel_atomic_plane.h" > +#include "intel_color.h" > +#include "intel_display_debugfs.h" > +#include "intel_display_types.h" > +#include "intel_pipe_crc.h" > +#include "intel_sprite.h" > + > +/* Primary plane formats for gen <= 3 */ > +static const u32 i8xx_primary_formats[] = { > + DRM_FORMAT_C8, > + DRM_FORMAT_XRGB1555, > + DRM_FORMAT_RGB565, > + DRM_FORMAT_XRGB8888, > +}; > + > +/* Primary plane formats for ivb (no fp16 due to hw issue) */ > +static const u32 ivb_primary_formats[] = { > + DRM_FORMAT_C8, > + DRM_FORMAT_RGB565, > + DRM_FORMAT_XRGB8888, > + DRM_FORMAT_XBGR8888, > + DRM_FORMAT_XRGB2101010, > + DRM_FORMAT_XBGR2101010, > +}; > + > +/* Primary plane formats for gen >= 4, except ivb */ > +static const u32 i965_primary_formats[] = { > + DRM_FORMAT_C8, > + DRM_FORMAT_RGB565, > + DRM_FORMAT_XRGB8888, > + DRM_FORMAT_XBGR8888, > + DRM_FORMAT_XRGB2101010, > + DRM_FORMAT_XBGR2101010, > + DRM_FORMAT_XBGR16161616F, > +}; > + > +/* Primary plane formats for vlv/chv */ > +static const u32 vlv_primary_formats[] = { > + DRM_FORMAT_C8, > + DRM_FORMAT_RGB565, > + DRM_FORMAT_XRGB8888, > + DRM_FORMAT_XBGR8888, > + DRM_FORMAT_ARGB8888, > + DRM_FORMAT_ABGR8888, > + DRM_FORMAT_XRGB2101010, > + DRM_FORMAT_XBGR2101010, > + DRM_FORMAT_ARGB2101010, > + DRM_FORMAT_ABGR2101010, > + DRM_FORMAT_XBGR16161616F, > +}; > + > +static const u64 i9xx_format_modifiers[] = { > + I915_FORMAT_MOD_X_TILED, > + DRM_FORMAT_MOD_LINEAR, > + DRM_FORMAT_MOD_INVALID > +}; > + > +static bool i8xx_plane_format_mod_supported(struct drm_plane *_plane, > + u32 format, u64 modifier) > +{ > + switch (modifier) { > + case DRM_FORMAT_MOD_LINEAR: > + case I915_FORMAT_MOD_X_TILED: > + break; > + default: > + return false; > + } > + > + switch (format) { > + case DRM_FORMAT_C8: > + case DRM_FORMAT_RGB565: > + case DRM_FORMAT_XRGB1555: > + case DRM_FORMAT_XRGB8888: > + return modifier == DRM_FORMAT_MOD_LINEAR || > + modifier == I915_FORMAT_MOD_X_TILED; > + default: > + return false; > + } > +} > + > +static bool i965_plane_format_mod_supported(struct drm_plane *_plane, > + u32 format, u64 modifier) > +{ > + switch (modifier) { > + case DRM_FORMAT_MOD_LINEAR: > + case I915_FORMAT_MOD_X_TILED: > + break; > + default: > + return false; > + } > + > + switch (format) { > + case DRM_FORMAT_C8: > + case DRM_FORMAT_RGB565: > + case DRM_FORMAT_XRGB8888: > + case DRM_FORMAT_XBGR8888: > + case DRM_FORMAT_ARGB8888: > + case DRM_FORMAT_ABGR8888: > + case DRM_FORMAT_XRGB2101010: > + case DRM_FORMAT_XBGR2101010: > + case DRM_FORMAT_ARGB2101010: > + case DRM_FORMAT_ABGR2101010: > + case DRM_FORMAT_XBGR16161616F: > + return modifier == DRM_FORMAT_MOD_LINEAR || > + modifier == I915_FORMAT_MOD_X_TILED; > + default: > + return false; > + } > +} > + > +static bool i9xx_plane_has_fbc(struct drm_i915_private *dev_priv, > + enum i9xx_plane_id i9xx_plane) > +{ > + if (!HAS_FBC(dev_priv)) > + return false; > + > + if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) > + return i9xx_plane == PLANE_A; /* tied to pipe A */ > + else if (IS_IVYBRIDGE(dev_priv)) > + return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B || > + i9xx_plane == PLANE_C; > + else if (INTEL_GEN(dev_priv) >= 4) > + return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B; > + else > + return i9xx_plane == PLANE_A; > +} > + > +static void assert_vblank_disabled(struct drm_crtc *crtc) > +{ > + if (I915_STATE_WARN_ON(drm_crtc_vblank_get(crtc) == 0)) > + drm_crtc_vblank_put(crtc); > +} > + > +u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc) > +{ > + struct drm_device *dev = crtc->base.dev; > + struct drm_vblank_crtc *vblank = &dev->vblank[drm_crtc_index(&crtc->base)]; > + > + if (!vblank->max_vblank_count) > + return (u32)drm_crtc_accurate_vblank_count(&crtc->base); > + > + return crtc->base.funcs->get_vblank_counter(&crtc->base); > +} > + > +u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state) > +{ > + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); > + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); > + u32 mode_flags = crtc->mode_flags; > + > + /* > + * From Gen 11, In case of dsi cmd mode, frame counter wouldnt > + * have updated at the beginning of TE, if we want to use > + * the hw counter, then we would find it updated in only > + * the next TE, hence switching to sw counter. > + */ > + if (mode_flags & (I915_MODE_FLAG_DSI_USE_TE0 | I915_MODE_FLAG_DSI_USE_TE1)) > + return 0; > + > + /* > + * On i965gm the hardware frame counter reads > + * zero when the TV encoder is enabled :( > + */ > + if (IS_I965GM(dev_priv) && > + (crtc_state->output_types & BIT(INTEL_OUTPUT_TVOUT))) > + return 0; > + > + if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) > + return 0xffffffff; /* full 32 bit counter */ > + else if (INTEL_GEN(dev_priv) >= 3) > + return 0xffffff; /* only 24 bits of frame count */ > + else > + return 0; /* Gen2 doesn't have a hardware frame counter */ > +} > + > +void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state) > +{ > + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); > + > + assert_vblank_disabled(&crtc->base); > + drm_crtc_set_max_vblank_count(&crtc->base, > + intel_crtc_max_vblank_count(crtc_state)); > + drm_crtc_vblank_on(&crtc->base); > +} > + > +void intel_crtc_vblank_off(const struct intel_crtc_state *crtc_state) > +{ > + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); > + > + drm_crtc_vblank_off(&crtc->base); > + assert_vblank_disabled(&crtc->base); > +} > + > +struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc) > +{ > + struct intel_crtc_state *crtc_state; > + > + crtc_state = kmalloc(sizeof(*crtc_state), GFP_KERNEL); > + > + if (crtc_state) > + intel_crtc_state_reset(crtc_state, crtc); > + > + return crtc_state; > +} > + > +void intel_crtc_state_reset(struct intel_crtc_state *crtc_state, > + struct intel_crtc *crtc) > +{ > + memset(crtc_state, 0, sizeof(*crtc_state)); > + > + __drm_atomic_helper_crtc_state_reset(&crtc_state->uapi, &crtc->base); > + > + crtc_state->cpu_transcoder = INVALID_TRANSCODER; > + crtc_state->master_transcoder = INVALID_TRANSCODER; > + crtc_state->hsw_workaround_pipe = INVALID_PIPE; > + crtc_state->output_format = INTEL_OUTPUT_FORMAT_INVALID; > + crtc_state->scaler_state.scaler_id = -1; > + crtc_state->mst_master_transcoder = INVALID_TRANSCODER; > +} > + > +static bool i9xx_plane_has_windowing(struct intel_plane *plane) > +{ > + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); > + enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; > + > + if (IS_CHERRYVIEW(dev_priv)) > + return i9xx_plane == PLANE_B; > + else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) > + return false; > + else if (IS_GEN(dev_priv, 4)) > + return i9xx_plane == PLANE_C; > + else > + return i9xx_plane == PLANE_B || > + i9xx_plane == PLANE_C; > +} > + > +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); > + const struct drm_framebuffer *fb = plane_state->hw.fb; > + unsigned int rotation = plane_state->hw.rotation; > + u32 dspcntr; > + > + dspcntr = DISPLAY_PLANE_ENABLE; > + > + if (IS_G4X(dev_priv) || IS_GEN(dev_priv, 5) || > + IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv)) > + dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; > + > + switch (fb->format->format) { > + case DRM_FORMAT_C8: > + dspcntr |= DISPPLANE_8BPP; > + break; > + case DRM_FORMAT_XRGB1555: > + dspcntr |= DISPPLANE_BGRX555; > + break; > + case DRM_FORMAT_ARGB1555: > + dspcntr |= DISPPLANE_BGRA555; > + break; > + case DRM_FORMAT_RGB565: > + dspcntr |= DISPPLANE_BGRX565; > + break; > + case DRM_FORMAT_XRGB8888: > + dspcntr |= DISPPLANE_BGRX888; > + break; > + case DRM_FORMAT_XBGR8888: > + dspcntr |= DISPPLANE_RGBX888; > + break; > + case DRM_FORMAT_ARGB8888: > + dspcntr |= DISPPLANE_BGRA888; > + break; > + case DRM_FORMAT_ABGR8888: > + dspcntr |= DISPPLANE_RGBA888; > + break; > + case DRM_FORMAT_XRGB2101010: > + dspcntr |= DISPPLANE_BGRX101010; > + break; > + case DRM_FORMAT_XBGR2101010: > + dspcntr |= DISPPLANE_RGBX101010; > + break; > + case DRM_FORMAT_ARGB2101010: > + dspcntr |= DISPPLANE_BGRA101010; > + break; > + case DRM_FORMAT_ABGR2101010: > + dspcntr |= DISPPLANE_RGBA101010; > + break; > + case DRM_FORMAT_XBGR16161616F: > + dspcntr |= DISPPLANE_RGBX161616; > + break; > + default: > + MISSING_CASE(fb->format->format); > + return 0; > + } > + > + if (INTEL_GEN(dev_priv) >= 4 && > + fb->modifier == I915_FORMAT_MOD_X_TILED) > + dspcntr |= DISPPLANE_TILED; > + > + if (rotation & DRM_MODE_ROTATE_180) > + dspcntr |= DISPPLANE_ROTATE_180; > + > + if (rotation & DRM_MODE_REFLECT_X) > + dspcntr |= DISPPLANE_MIRROR; > + > + return dspcntr; > +} > + > +static int > +i9xx_plane_check(struct intel_crtc_state *crtc_state, > + struct intel_plane_state *plane_state) > +{ > + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); > + int ret; > + > + ret = chv_plane_check_rotation(plane_state); > + if (ret) > + return ret; > + > + ret = intel_atomic_plane_check_clipping(plane_state, crtc_state, > + DRM_PLANE_HELPER_NO_SCALING, > + DRM_PLANE_HELPER_NO_SCALING, > + i9xx_plane_has_windowing(plane)); > + if (ret) > + return ret; > + > + ret = i9xx_check_plane_surface(plane_state); > + if (ret) > + return ret; > + > + if (!plane_state->uapi.visible) > + return 0; > + > + ret = intel_plane_check_src_coordinates(plane_state); > + if (ret) > + return ret; > + > + plane_state->ctl = i9xx_plane_ctl(crtc_state, plane_state); > + > + return 0; > +} > + > +static u32 i9xx_plane_ctl_crtc(const struct intel_crtc_state *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) > + dspcntr |= DISPPLANE_GAMMA_ENABLE; > + > + if (crtc_state->csc_enable) > + dspcntr |= DISPPLANE_PIPE_CSC_ENABLE; > + > + if (INTEL_GEN(dev_priv) < 5) > + dspcntr |= DISPPLANE_SEL_PIPE(crtc->pipe); > + > + return dspcntr; > +} > + > +static void i9xx_plane_ratio(const struct intel_crtc_state *crtc_state, > + const struct intel_plane_state *plane_state, > + unsigned int *num, unsigned int *den) > +{ > + const struct drm_framebuffer *fb = plane_state->hw.fb; > + unsigned int cpp = fb->format->cpp[0]; > + > + /* > + * g4x bspec says 64bpp pixel rate can't exceed 80% > + * of cdclk when the sprite plane is enabled on the > + * same pipe. ilk/snb bspec says 64bpp pixel rate is > + * never allowed to exceed 80% of cdclk. Let's just go > + * with the ilk/snb limit always. > + */ > + if (cpp == 8) { > + *num = 10; > + *den = 8; > + } else { > + *num = 1; > + *den = 1; > + } > +} > + > +static int i9xx_plane_min_cdclk(const struct intel_crtc_state *crtc_state, > + const struct intel_plane_state *plane_state) > +{ > + unsigned int pixel_rate; > + unsigned int num, den; > + > + /* > + * Note that crtc_state->pixel_rate accounts for both > + * horizontal and vertical panel fitter downscaling factors. > + * Pre-HSW bspec tells us to only consider the horizontal > + * downscaling factor here. We ignore that and just consider > + * both for simplicity. > + */ > + pixel_rate = crtc_state->pixel_rate; > + > + i9xx_plane_ratio(crtc_state, plane_state, &num, &den); > + > + /* two pixels per clock with double wide pipe */ > + if (crtc_state->double_wide) > + den *= 2; > + > + return DIV_ROUND_UP(pixel_rate * num, den); > +} > + > +static void i9xx_update_plane(struct intel_plane *plane, > + 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); > + enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; > + u32 linear_offset; > + int x = plane_state->color_plane[0].x; > + int y = plane_state->color_plane[0].y; > + 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); > + unsigned long irqflags; > + u32 dspaddr_offset; > + u32 dspcntr; > + > + dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state); > + > + linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); > + > + if (INTEL_GEN(dev_priv) >= 4) > + dspaddr_offset = plane_state->color_plane[0].offset; > + else > + dspaddr_offset = linear_offset; > + > + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); > + > + intel_de_write_fw(dev_priv, DSPSTRIDE(i9xx_plane), > + plane_state->color_plane[0].stride); > + > + if (INTEL_GEN(dev_priv) < 4) { > + /* > + * PLANE_A doesn't actually have a full window > + * generator but let's assume we still need to > + * program whatever is there. > + */ > + intel_de_write_fw(dev_priv, DSPPOS(i9xx_plane), > + (crtc_y << 16) | crtc_x); > + intel_de_write_fw(dev_priv, DSPSIZE(i9xx_plane), > + ((crtc_h - 1) << 16) | (crtc_w - 1)); > + } else if (IS_CHERRYVIEW(dev_priv) && i9xx_plane == PLANE_B) { > + intel_de_write_fw(dev_priv, PRIMPOS(i9xx_plane), > + (crtc_y << 16) | crtc_x); > + intel_de_write_fw(dev_priv, PRIMSIZE(i9xx_plane), > + ((crtc_h - 1) << 16) | (crtc_w - 1)); > + intel_de_write_fw(dev_priv, PRIMCNSTALPHA(i9xx_plane), 0); > + } > + > + if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { > + intel_de_write_fw(dev_priv, DSPOFFSET(i9xx_plane), > + (y << 16) | x); > + } else if (INTEL_GEN(dev_priv) >= 4) { > + intel_de_write_fw(dev_priv, DSPLINOFF(i9xx_plane), > + linear_offset); > + intel_de_write_fw(dev_priv, DSPTILEOFF(i9xx_plane), > + (y << 16) | x); > + } > + > + /* > + * The control register self-arms if the plane was previously > + * 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(i9xx_plane), dspcntr); > + if (INTEL_GEN(dev_priv) >= 4) > + intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), > + intel_plane_ggtt_offset(plane_state) + dspaddr_offset); > + else > + intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), > + intel_plane_ggtt_offset(plane_state) + dspaddr_offset); > + > + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); > +} > + > +static void i9xx_disable_plane(struct intel_plane *plane, > + const struct intel_crtc_state *crtc_state) > +{ > + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); > + enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; > + unsigned long irqflags; > + u32 dspcntr; > + > + /* > + * DSPCNTR pipe gamma enable on g4x+ and pipe csc > + * enable on ilk+ affect the pipe bottom color as > + * well, so we must configure them even if the plane > + * is disabled. > + * > + * On pre-g4x there is no way to gamma correct the > + * pipe bottom color but we'll keep on doing this > + * anyway so that the crtc state readout works correctly. > + */ > + dspcntr = i9xx_plane_ctl_crtc(crtc_state); > + > + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); > + > + intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr); > + if (INTEL_GEN(dev_priv) >= 4) > + intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), 0); > + else > + intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), 0); > + > + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); > +} > + > +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); > + enum intel_display_power_domain power_domain; > + enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; > + intel_wakeref_t wakeref; > + bool ret; > + u32 val; > + > + /* > + * Not 100% correct for planes that can move between pipes, > + * but that's only the case for gen2-4 which don't have any > + * display power wells. > + */ > + power_domain = POWER_DOMAIN_PIPE(plane->pipe); > + wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain); > + if (!wakeref) > + return false; > + > + val = intel_de_read(dev_priv, DSPCNTR(i9xx_plane)); > + > + ret = val & DISPLAY_PLANE_ENABLE; > + > + if (INTEL_GEN(dev_priv) >= 5) > + *pipe = plane->pipe; > + else > + *pipe = (val & DISPPLANE_SEL_PIPE_MASK) >> > + DISPPLANE_SEL_PIPE_SHIFT; > + > + intel_display_power_put(dev_priv, power_domain, wakeref); > + > + return ret; > +} > + > +unsigned int > +i9xx_plane_max_stride(struct intel_plane *plane, > + u32 pixel_format, u64 modifier, > + unsigned int rotation) > +{ > + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); > + > + if (!HAS_GMCH(dev_priv)) { > + return 32*1024; > + } else if (INTEL_GEN(dev_priv) >= 4) { > + if (modifier == I915_FORMAT_MOD_X_TILED) > + return 16*1024; > + else > + return 32*1024; > + } else if (INTEL_GEN(dev_priv) >= 3) { > + if (modifier == I915_FORMAT_MOD_X_TILED) > + return 8*1024; > + else > + return 16*1024; > + } else { > + if (plane->i9xx_plane == PLANE_C) > + return 4*1024; > + else > + return 8*1024; > + } > +} > + > +static const struct drm_plane_funcs i965_plane_funcs = { > + .update_plane = drm_atomic_helper_update_plane, > + .disable_plane = drm_atomic_helper_disable_plane, > + .destroy = intel_plane_destroy, > + .atomic_duplicate_state = intel_plane_duplicate_state, > + .atomic_destroy_state = intel_plane_destroy_state, > + .format_mod_supported = i965_plane_format_mod_supported, > +}; > + > +static const struct drm_plane_funcs i8xx_plane_funcs = { > + .update_plane = drm_atomic_helper_update_plane, > + .disable_plane = drm_atomic_helper_disable_plane, > + .destroy = intel_plane_destroy, > + .atomic_duplicate_state = intel_plane_duplicate_state, > + .atomic_destroy_state = intel_plane_destroy_state, > + .format_mod_supported = i8xx_plane_format_mod_supported, > +}; > + > +static struct intel_plane * > +intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) > +{ > + struct intel_plane *plane; > + const struct drm_plane_funcs *plane_funcs; > + unsigned int supported_rotations; > + const u32 *formats; > + int num_formats; > + int ret, zpos; > + > + if (INTEL_GEN(dev_priv) >= 9) > + return skl_universal_plane_create(dev_priv, pipe, > + PLANE_PRIMARY); > + > + plane = intel_plane_alloc(); > + if (IS_ERR(plane)) > + return plane; > + > + plane->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) && INTEL_GEN(dev_priv) < 4 && > + INTEL_NUM_PIPES(dev_priv) == 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); > + > + plane->has_fbc = i9xx_plane_has_fbc(dev_priv, plane->i9xx_plane); > + if (plane->has_fbc) { > + struct intel_fbc *fbc = &dev_priv->fbc; > + > + fbc->possible_framebuffer_bits |= plane->frontbuffer_bit; > + } > + > + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { > + formats = vlv_primary_formats; > + num_formats = ARRAY_SIZE(vlv_primary_formats); > + } else if (INTEL_GEN(dev_priv) >= 4) { > + /* > + * WaFP16GammaEnabling:ivb > + * "Workaround : When using the 64-bit format, the plane > + * output on each color channel has one quarter amplitude. > + * It can be brought up to full amplitude by using pipe > + * gamma correction or pipe color space conversion to > + * multiply the plane output by four." > + * > + * There is no dedicated plane gamma for the primary plane, > + * and using the pipe gamma/csc could conflict with other > + * 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)) { > + formats = ivb_primary_formats; > + num_formats = ARRAY_SIZE(ivb_primary_formats); > + } else { > + formats = i965_primary_formats; > + num_formats = ARRAY_SIZE(i965_primary_formats); > + } > + } else { > + formats = i8xx_primary_formats; > + num_formats = ARRAY_SIZE(i8xx_primary_formats); > + } > + > + if (INTEL_GEN(dev_priv) >= 4) > + plane_funcs = &i965_plane_funcs; > + else > + plane_funcs = &i8xx_plane_funcs; > + > + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) > + plane->min_cdclk = vlv_plane_min_cdclk; > + else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) > + plane->min_cdclk = hsw_plane_min_cdclk; > + else if (IS_IVYBRIDGE(dev_priv)) > + plane->min_cdclk = ivb_plane_min_cdclk; > + else > + plane->min_cdclk = i9xx_plane_min_cdclk; > + > + plane->max_stride = i9xx_plane_max_stride; > + plane->update_plane = i9xx_update_plane; > + plane->disable_plane = i9xx_disable_plane; > + plane->get_hw_state = i9xx_plane_get_hw_state; > + plane->check_plane = i9xx_plane_check; > + > + if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) > + ret = drm_universal_plane_init(&dev_priv->drm, &plane->base, > + 0, plane_funcs, > + formats, num_formats, > + i9xx_format_modifiers, > + DRM_PLANE_TYPE_PRIMARY, > + "primary %c", pipe_name(pipe)); > + else > + ret = drm_universal_plane_init(&dev_priv->drm, &plane->base, > + 0, plane_funcs, > + formats, num_formats, > + i9xx_format_modifiers, > + DRM_PLANE_TYPE_PRIMARY, > + "plane %c", > + plane_name(plane->i9xx_plane)); > + if (ret) > + goto fail; > + > + if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) { > + supported_rotations = > + DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 | > + DRM_MODE_REFLECT_X; > + } else if (INTEL_GEN(dev_priv) >= 4) { > + supported_rotations = > + DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180; > + } else { > + supported_rotations = DRM_MODE_ROTATE_0; > + } > + > + if (INTEL_GEN(dev_priv) >= 4) > + drm_plane_create_rotation_property(&plane->base, > + DRM_MODE_ROTATE_0, > + supported_rotations); > + > + zpos = 0; > + drm_plane_create_zpos_immutable_property(&plane->base, zpos); > + > + drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs); > + > + return plane; > + > +fail: > + intel_plane_free(plane); > + > + return ERR_PTR(ret); > +} > + > +static struct intel_crtc *intel_crtc_alloc(void) > +{ > + struct intel_crtc_state *crtc_state; > + struct intel_crtc *crtc; > + > + crtc = kzalloc(sizeof(*crtc), GFP_KERNEL); > + if (!crtc) > + return ERR_PTR(-ENOMEM); > + > + crtc_state = intel_crtc_state_alloc(crtc); > + if (!crtc_state) { > + kfree(crtc); > + return ERR_PTR(-ENOMEM); > + } > + > + crtc->base.state = &crtc_state->uapi; > + crtc->config = crtc_state; > + > + return crtc; > +} > + > +static void intel_crtc_free(struct intel_crtc *crtc) > +{ > + intel_crtc_destroy_state(&crtc->base, crtc->base.state); > + kfree(crtc); > +} > + > +static void intel_crtc_destroy(struct drm_crtc *crtc) > +{ > + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); > + > + drm_crtc_cleanup(crtc); > + kfree(intel_crtc); > +} > + > +static int intel_crtc_late_register(struct drm_crtc *crtc) > +{ > + intel_crtc_debugfs_add(crtc); > + return 0; > +} > + > +#define INTEL_CRTC_FUNCS \ > + .gamma_set = drm_atomic_helper_legacy_gamma_set, \ > + .set_config = drm_atomic_helper_set_config, \ > + .destroy = intel_crtc_destroy, \ > + .page_flip = drm_atomic_helper_page_flip, \ > + .atomic_duplicate_state = intel_crtc_duplicate_state, \ > + .atomic_destroy_state = intel_crtc_destroy_state, \ > + .set_crc_source = intel_crtc_set_crc_source, \ > + .verify_crc_source = intel_crtc_verify_crc_source, \ > + .get_crc_sources = intel_crtc_get_crc_sources, \ > + .late_register = intel_crtc_late_register > + > +static const struct drm_crtc_funcs bdw_crtc_funcs = { > + INTEL_CRTC_FUNCS, > + > + .get_vblank_counter = g4x_get_vblank_counter, > + .enable_vblank = bdw_enable_vblank, > + .disable_vblank = bdw_disable_vblank, > + .get_vblank_timestamp = intel_crtc_get_vblank_timestamp, > +}; > + > +static const struct drm_crtc_funcs ilk_crtc_funcs = { > + INTEL_CRTC_FUNCS, > + > + .get_vblank_counter = g4x_get_vblank_counter, > + .enable_vblank = ilk_enable_vblank, > + .disable_vblank = ilk_disable_vblank, > + .get_vblank_timestamp = intel_crtc_get_vblank_timestamp, > +}; > + > +static const struct drm_crtc_funcs g4x_crtc_funcs = { > + INTEL_CRTC_FUNCS, > + > + .get_vblank_counter = g4x_get_vblank_counter, > + .enable_vblank = i965_enable_vblank, > + .disable_vblank = i965_disable_vblank, > + .get_vblank_timestamp = intel_crtc_get_vblank_timestamp, > +}; > + > +static const struct drm_crtc_funcs i965_crtc_funcs = { > + INTEL_CRTC_FUNCS, > + > + .get_vblank_counter = i915_get_vblank_counter, > + .enable_vblank = i965_enable_vblank, > + .disable_vblank = i965_disable_vblank, > + .get_vblank_timestamp = intel_crtc_get_vblank_timestamp, > +}; > + > +static const struct drm_crtc_funcs i915gm_crtc_funcs = { > + INTEL_CRTC_FUNCS, > + > + .get_vblank_counter = i915_get_vblank_counter, > + .enable_vblank = i915gm_enable_vblank, > + .disable_vblank = i915gm_disable_vblank, > + .get_vblank_timestamp = intel_crtc_get_vblank_timestamp, > +}; > + > +static const struct drm_crtc_funcs i915_crtc_funcs = { > + INTEL_CRTC_FUNCS, > + > + .get_vblank_counter = i915_get_vblank_counter, > + .enable_vblank = i8xx_enable_vblank, > + .disable_vblank = i8xx_disable_vblank, > + .get_vblank_timestamp = intel_crtc_get_vblank_timestamp, > +}; > + > +static const struct drm_crtc_funcs i8xx_crtc_funcs = { > + INTEL_CRTC_FUNCS, > + > + /* no hw vblank counter */ > + .enable_vblank = i8xx_enable_vblank, > + .disable_vblank = i8xx_disable_vblank, > + .get_vblank_timestamp = intel_crtc_get_vblank_timestamp, > +}; > + > +int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe) > +{ > + struct intel_plane *primary, *cursor; > + const struct drm_crtc_funcs *funcs; > + struct intel_crtc *crtc; > + int sprite, ret; > + > + crtc = intel_crtc_alloc(); > + if (IS_ERR(crtc)) > + return PTR_ERR(crtc); > + > + crtc->pipe = pipe; > + crtc->num_scalers = RUNTIME_INFO(dev_priv)->num_scalers[pipe]; > + > + primary = intel_primary_plane_create(dev_priv, pipe); > + if (IS_ERR(primary)) { > + ret = PTR_ERR(primary); > + goto fail; > + } > + crtc->plane_ids_mask |= BIT(primary->id); > + > + for_each_sprite(dev_priv, pipe, sprite) { > + struct intel_plane *plane; > + > + plane = intel_sprite_plane_create(dev_priv, pipe, sprite); > + if (IS_ERR(plane)) { > + ret = PTR_ERR(plane); > + goto fail; > + } > + crtc->plane_ids_mask |= BIT(plane->id); > + } > + > + cursor = intel_cursor_plane_create(dev_priv, pipe); > + if (IS_ERR(cursor)) { > + ret = PTR_ERR(cursor); > + goto fail; > + } > + crtc->plane_ids_mask |= BIT(cursor->id); > + > + if (HAS_GMCH(dev_priv)) { > + if (IS_CHERRYVIEW(dev_priv) || > + IS_VALLEYVIEW(dev_priv) || IS_G4X(dev_priv)) > + funcs = &g4x_crtc_funcs; > + else if (IS_GEN(dev_priv, 4)) > + funcs = &i965_crtc_funcs; > + else if (IS_I945GM(dev_priv) || IS_I915GM(dev_priv)) > + funcs = &i915gm_crtc_funcs; > + else if (IS_GEN(dev_priv, 3)) > + funcs = &i915_crtc_funcs; > + else > + funcs = &i8xx_crtc_funcs; > + } else { > + if (INTEL_GEN(dev_priv) >= 8) > + funcs = &bdw_crtc_funcs; > + else > + funcs = &ilk_crtc_funcs; > + } > + > + ret = drm_crtc_init_with_planes(&dev_priv->drm, &crtc->base, > + &primary->base, &cursor->base, > + funcs, "pipe %c", pipe_name(pipe)); > + if (ret) > + goto fail; > + > + BUG_ON(pipe >= ARRAY_SIZE(dev_priv->pipe_to_crtc_mapping) || > + dev_priv->pipe_to_crtc_mapping[pipe] != NULL); > + dev_priv->pipe_to_crtc_mapping[pipe] = crtc; > + > + if (INTEL_GEN(dev_priv) < 9) { > + enum i9xx_plane_id i9xx_plane = primary->i9xx_plane; > + > + BUG_ON(i9xx_plane >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) || > + dev_priv->plane_to_crtc_mapping[i9xx_plane] != NULL); > + dev_priv->plane_to_crtc_mapping[i9xx_plane] = crtc; > + } > + > + if (INTEL_GEN(dev_priv) >= 10) > + drm_crtc_create_scaling_filter_property(&crtc->base, > + BIT(DRM_SCALING_FILTER_DEFAULT) | > + BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR)); > + > + intel_color_init(crtc); > + > + intel_crtc_crc_init(crtc); > + > + drm_WARN_ON(&dev_priv->drm, drm_crtc_index(&crtc->base) != crtc->pipe); > + > + return 0; > + > +fail: > + intel_crtc_free(crtc); > + > + return ret; > +} > diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c > index 722a1cf61941..2507a72ee249 100644 > --- a/drivers/gpu/drm/i915/display/intel_display.c > +++ b/drivers/gpu/drm/i915/display/intel_display.c > @@ -87,56 +87,6 @@ > #include "intel_tc.h" > #include "intel_vga.h" > > -/* Primary plane formats for gen <= 3 */ > -static const u32 i8xx_primary_formats[] = { > - DRM_FORMAT_C8, > - DRM_FORMAT_XRGB1555, > - DRM_FORMAT_RGB565, > - DRM_FORMAT_XRGB8888, > -}; > - > -/* Primary plane formats for ivb (no fp16 due to hw issue) */ > -static const u32 ivb_primary_formats[] = { > - DRM_FORMAT_C8, > - DRM_FORMAT_RGB565, > - DRM_FORMAT_XRGB8888, > - DRM_FORMAT_XBGR8888, > - DRM_FORMAT_XRGB2101010, > - DRM_FORMAT_XBGR2101010, > -}; > - > -/* Primary plane formats for gen >= 4, except ivb */ > -static const u32 i965_primary_formats[] = { > - DRM_FORMAT_C8, > - DRM_FORMAT_RGB565, > - DRM_FORMAT_XRGB8888, > - DRM_FORMAT_XBGR8888, > - DRM_FORMAT_XRGB2101010, > - DRM_FORMAT_XBGR2101010, > - DRM_FORMAT_XBGR16161616F, > -}; > - > -/* Primary plane formats for vlv/chv */ > -static const u32 vlv_primary_formats[] = { > - DRM_FORMAT_C8, > - DRM_FORMAT_RGB565, > - DRM_FORMAT_XRGB8888, > - DRM_FORMAT_XBGR8888, > - DRM_FORMAT_ARGB8888, > - DRM_FORMAT_ABGR8888, > - DRM_FORMAT_XRGB2101010, > - DRM_FORMAT_XBGR2101010, > - DRM_FORMAT_ARGB2101010, > - DRM_FORMAT_ABGR2101010, > - DRM_FORMAT_XBGR16161616F, > -}; > - > -static const u64 i9xx_format_modifiers[] = { > - I915_FORMAT_MOD_X_TILED, > - DRM_FORMAT_MOD_LINEAR, > - DRM_FORMAT_MOD_INVALID > -}; > - > static void i9xx_crtc_clock_get(struct intel_crtc *crtc, > struct intel_crtc_state *pipe_config); > static void ilk_pch_clock_get(struct intel_crtc *crtc, > @@ -162,7 +112,6 @@ static void skl_pfit_enable(const struct intel_crtc_state *crtc_state); > static void ilk_pfit_enable(const struct intel_crtc_state *crtc_state); > static void intel_modeset_setup_hw_state(struct drm_device *dev, > struct drm_modeset_acquire_ctx *ctx); > -static struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc); > > struct intel_limit { > struct { > @@ -1301,12 +1250,6 @@ static void assert_planes_disabled(struct intel_crtc *crtc) > assert_plane_disabled(plane); > } > > -static void assert_vblank_disabled(struct drm_crtc *crtc) > -{ > - if (I915_STATE_WARN_ON(drm_crtc_vblank_get(crtc) == 0)) > - drm_crtc_vblank_put(crtc); > -} > - > void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv, > enum pipe pipe) > { > @@ -1791,55 +1734,6 @@ enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc) > return crtc->pipe; > } > > -static u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state) > -{ > - struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); > - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); > - u32 mode_flags = crtc->mode_flags; > - > - /* > - * From Gen 11, In case of dsi cmd mode, frame counter wouldnt > - * have updated at the beginning of TE, if we want to use > - * the hw counter, then we would find it updated in only > - * the next TE, hence switching to sw counter. > - */ > - if (mode_flags & (I915_MODE_FLAG_DSI_USE_TE0 | I915_MODE_FLAG_DSI_USE_TE1)) > - return 0; > - > - /* > - * On i965gm the hardware frame counter reads > - * zero when the TV encoder is enabled :( > - */ > - if (IS_I965GM(dev_priv) && > - (crtc_state->output_types & BIT(INTEL_OUTPUT_TVOUT))) > - return 0; > - > - if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) > - return 0xffffffff; /* full 32 bit counter */ > - else if (INTEL_GEN(dev_priv) >= 3) > - return 0xffffff; /* only 24 bits of frame count */ > - else > - return 0; /* Gen2 doesn't have a hardware frame counter */ > -} > - > -void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state) > -{ > - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); > - > - assert_vblank_disabled(&crtc->base); > - drm_crtc_set_max_vblank_count(&crtc->base, > - intel_crtc_max_vblank_count(crtc_state)); > - drm_crtc_vblank_on(&crtc->base); > -} > - > -void intel_crtc_vblank_off(const struct intel_crtc_state *crtc_state) > -{ > - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); > - > - drm_crtc_vblank_off(&crtc->base); > - assert_vblank_disabled(&crtc->base); > -} > - > void intel_enable_pipe(const struct intel_crtc_state *new_crtc_state) > { > struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); > @@ -4046,171 +3940,6 @@ int skl_check_plane_surface(struct intel_plane_state *plane_state) > return 0; > } > > -static void i9xx_plane_ratio(const struct intel_crtc_state *crtc_state, > - const struct intel_plane_state *plane_state, > - unsigned int *num, unsigned int *den) > -{ > - const struct drm_framebuffer *fb = plane_state->hw.fb; > - unsigned int cpp = fb->format->cpp[0]; > - > - /* > - * g4x bspec says 64bpp pixel rate can't exceed 80% > - * of cdclk when the sprite plane is enabled on the > - * same pipe. ilk/snb bspec says 64bpp pixel rate is > - * never allowed to exceed 80% of cdclk. Let's just go > - * with the ilk/snb limit always. > - */ > - if (cpp == 8) { > - *num = 10; > - *den = 8; > - } else { > - *num = 1; > - *den = 1; > - } > -} > - > -static int i9xx_plane_min_cdclk(const struct intel_crtc_state *crtc_state, > - const struct intel_plane_state *plane_state) > -{ > - unsigned int pixel_rate; > - unsigned int num, den; > - > - /* > - * Note that crtc_state->pixel_rate accounts for both > - * horizontal and vertical panel fitter downscaling factors. > - * Pre-HSW bspec tells us to only consider the horizontal > - * downscaling factor here. We ignore that and just consider > - * both for simplicity. > - */ > - pixel_rate = crtc_state->pixel_rate; > - > - i9xx_plane_ratio(crtc_state, plane_state, &num, &den); > - > - /* two pixels per clock with double wide pipe */ > - if (crtc_state->double_wide) > - den *= 2; > - > - return DIV_ROUND_UP(pixel_rate * num, den); > -} > - > -unsigned int > -i9xx_plane_max_stride(struct intel_plane *plane, > - u32 pixel_format, u64 modifier, > - unsigned int rotation) > -{ > - struct drm_i915_private *dev_priv = to_i915(plane->base.dev); > - > - if (!HAS_GMCH(dev_priv)) { > - return 32*1024; > - } else if (INTEL_GEN(dev_priv) >= 4) { > - if (modifier == I915_FORMAT_MOD_X_TILED) > - return 16*1024; > - else > - return 32*1024; > - } else if (INTEL_GEN(dev_priv) >= 3) { > - if (modifier == I915_FORMAT_MOD_X_TILED) > - return 8*1024; > - else > - return 16*1024; > - } else { > - if (plane->i9xx_plane == PLANE_C) > - return 4*1024; > - else > - return 8*1024; > - } > -} > - > -static u32 i9xx_plane_ctl_crtc(const struct intel_crtc_state *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) > - dspcntr |= DISPPLANE_GAMMA_ENABLE; > - > - if (crtc_state->csc_enable) > - dspcntr |= DISPPLANE_PIPE_CSC_ENABLE; > - > - if (INTEL_GEN(dev_priv) < 5) > - dspcntr |= DISPPLANE_SEL_PIPE(crtc->pipe); > - > - return dspcntr; > -} > - > -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); > - const struct drm_framebuffer *fb = plane_state->hw.fb; > - unsigned int rotation = plane_state->hw.rotation; > - u32 dspcntr; > - > - dspcntr = DISPLAY_PLANE_ENABLE; > - > - if (IS_G4X(dev_priv) || IS_GEN(dev_priv, 5) || > - IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv)) > - dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; > - > - switch (fb->format->format) { > - case DRM_FORMAT_C8: > - dspcntr |= DISPPLANE_8BPP; > - break; > - case DRM_FORMAT_XRGB1555: > - dspcntr |= DISPPLANE_BGRX555; > - break; > - case DRM_FORMAT_ARGB1555: > - dspcntr |= DISPPLANE_BGRA555; > - break; > - case DRM_FORMAT_RGB565: > - dspcntr |= DISPPLANE_BGRX565; > - break; > - case DRM_FORMAT_XRGB8888: > - dspcntr |= DISPPLANE_BGRX888; > - break; > - case DRM_FORMAT_XBGR8888: > - dspcntr |= DISPPLANE_RGBX888; > - break; > - case DRM_FORMAT_ARGB8888: > - dspcntr |= DISPPLANE_BGRA888; > - break; > - case DRM_FORMAT_ABGR8888: > - dspcntr |= DISPPLANE_RGBA888; > - break; > - case DRM_FORMAT_XRGB2101010: > - dspcntr |= DISPPLANE_BGRX101010; > - break; > - case DRM_FORMAT_XBGR2101010: > - dspcntr |= DISPPLANE_RGBX101010; > - break; > - case DRM_FORMAT_ARGB2101010: > - dspcntr |= DISPPLANE_BGRA101010; > - break; > - case DRM_FORMAT_ABGR2101010: > - dspcntr |= DISPPLANE_RGBA101010; > - break; > - case DRM_FORMAT_XBGR16161616F: > - dspcntr |= DISPPLANE_RGBX161616; > - break; > - default: > - MISSING_CASE(fb->format->format); > - return 0; > - } > - > - if (INTEL_GEN(dev_priv) >= 4 && > - fb->modifier == I915_FORMAT_MOD_X_TILED) > - dspcntr |= DISPPLANE_TILED; > - > - if (rotation & DRM_MODE_ROTATE_180) > - dspcntr |= DISPPLANE_ROTATE_180; > - > - if (rotation & DRM_MODE_REFLECT_X) > - dspcntr |= DISPPLANE_MIRROR; > - > - return dspcntr; > -} > - > int i9xx_check_plane_surface(struct intel_plane_state *plane_state) > { > struct drm_i915_private *dev_priv = > @@ -4271,197 +4000,6 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state) > return 0; > } > > -static bool i9xx_plane_has_windowing(struct intel_plane *plane) > -{ > - struct drm_i915_private *dev_priv = to_i915(plane->base.dev); > - enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; > - > - if (IS_CHERRYVIEW(dev_priv)) > - return i9xx_plane == PLANE_B; > - else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) > - return false; > - else if (IS_GEN(dev_priv, 4)) > - return i9xx_plane == PLANE_C; > - else > - return i9xx_plane == PLANE_B || > - i9xx_plane == PLANE_C; > -} > - > -static int > -i9xx_plane_check(struct intel_crtc_state *crtc_state, > - struct intel_plane_state *plane_state) > -{ > - struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); > - int ret; > - > - ret = chv_plane_check_rotation(plane_state); > - if (ret) > - return ret; > - > - ret = intel_atomic_plane_check_clipping(plane_state, crtc_state, > - DRM_PLANE_HELPER_NO_SCALING, > - DRM_PLANE_HELPER_NO_SCALING, > - i9xx_plane_has_windowing(plane)); > - if (ret) > - return ret; > - > - ret = i9xx_check_plane_surface(plane_state); > - if (ret) > - return ret; > - > - if (!plane_state->uapi.visible) > - return 0; > - > - ret = intel_plane_check_src_coordinates(plane_state); > - if (ret) > - return ret; > - > - plane_state->ctl = i9xx_plane_ctl(crtc_state, plane_state); > - > - return 0; > -} > - > -static void i9xx_update_plane(struct intel_plane *plane, > - 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); > - enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; > - u32 linear_offset; > - int x = plane_state->color_plane[0].x; > - int y = plane_state->color_plane[0].y; > - 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); > - unsigned long irqflags; > - u32 dspaddr_offset; > - u32 dspcntr; > - > - dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state); > - > - linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); > - > - if (INTEL_GEN(dev_priv) >= 4) > - dspaddr_offset = plane_state->color_plane[0].offset; > - else > - dspaddr_offset = linear_offset; > - > - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); > - > - intel_de_write_fw(dev_priv, DSPSTRIDE(i9xx_plane), > - plane_state->color_plane[0].stride); > - > - if (INTEL_GEN(dev_priv) < 4) { > - /* > - * PLANE_A doesn't actually have a full window > - * generator but let's assume we still need to > - * program whatever is there. > - */ > - intel_de_write_fw(dev_priv, DSPPOS(i9xx_plane), > - (crtc_y << 16) | crtc_x); > - intel_de_write_fw(dev_priv, DSPSIZE(i9xx_plane), > - ((crtc_h - 1) << 16) | (crtc_w - 1)); > - } else if (IS_CHERRYVIEW(dev_priv) && i9xx_plane == PLANE_B) { > - intel_de_write_fw(dev_priv, PRIMPOS(i9xx_plane), > - (crtc_y << 16) | crtc_x); > - intel_de_write_fw(dev_priv, PRIMSIZE(i9xx_plane), > - ((crtc_h - 1) << 16) | (crtc_w - 1)); > - intel_de_write_fw(dev_priv, PRIMCNSTALPHA(i9xx_plane), 0); > - } > - > - if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { > - intel_de_write_fw(dev_priv, DSPOFFSET(i9xx_plane), > - (y << 16) | x); > - } else if (INTEL_GEN(dev_priv) >= 4) { > - intel_de_write_fw(dev_priv, DSPLINOFF(i9xx_plane), > - linear_offset); > - intel_de_write_fw(dev_priv, DSPTILEOFF(i9xx_plane), > - (y << 16) | x); > - } > - > - /* > - * The control register self-arms if the plane was previously > - * 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(i9xx_plane), dspcntr); > - if (INTEL_GEN(dev_priv) >= 4) > - intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), > - intel_plane_ggtt_offset(plane_state) + dspaddr_offset); > - else > - intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), > - intel_plane_ggtt_offset(plane_state) + dspaddr_offset); > - > - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); > -} > - > -static void i9xx_disable_plane(struct intel_plane *plane, > - const struct intel_crtc_state *crtc_state) > -{ > - struct drm_i915_private *dev_priv = to_i915(plane->base.dev); > - enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; > - unsigned long irqflags; > - u32 dspcntr; > - > - /* > - * DSPCNTR pipe gamma enable on g4x+ and pipe csc > - * enable on ilk+ affect the pipe bottom color as > - * well, so we must configure them even if the plane > - * is disabled. > - * > - * On pre-g4x there is no way to gamma correct the > - * pipe bottom color but we'll keep on doing this > - * anyway so that the crtc state readout works correctly. > - */ > - dspcntr = i9xx_plane_ctl_crtc(crtc_state); > - > - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); > - > - intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr); > - if (INTEL_GEN(dev_priv) >= 4) > - intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), 0); > - else > - intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), 0); > - > - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); > -} > - > -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); > - enum intel_display_power_domain power_domain; > - enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; > - intel_wakeref_t wakeref; > - bool ret; > - u32 val; > - > - /* > - * Not 100% correct for planes that can move between pipes, > - * but that's only the case for gen2-4 which don't have any > - * display power wells. > - */ > - power_domain = POWER_DOMAIN_PIPE(plane->pipe); > - wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain); > - if (!wakeref) > - return false; > - > - val = intel_de_read(dev_priv, DSPCNTR(i9xx_plane)); > - > - ret = val & DISPLAY_PLANE_ENABLE; > - > - if (INTEL_GEN(dev_priv) >= 5) > - *pipe = plane->pipe; > - else > - *pipe = (val & DISPPLANE_SEL_PIPE_MASK) >> > - DISPPLANE_SEL_PIPE_SHIFT; > - > - intel_display_power_put(dev_priv, power_domain, wakeref); > - > - return ret; > -} > - > static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id) > { > struct drm_device *dev = intel_crtc->base.dev; > @@ -11908,33 +11446,6 @@ static void ilk_pch_clock_get(struct intel_crtc *crtc, > &pipe_config->fdi_m_n); > } > > -static void intel_crtc_state_reset(struct intel_crtc_state *crtc_state, > - struct intel_crtc *crtc) > -{ > - memset(crtc_state, 0, sizeof(*crtc_state)); > - > - __drm_atomic_helper_crtc_state_reset(&crtc_state->uapi, &crtc->base); > - > - crtc_state->cpu_transcoder = INVALID_TRANSCODER; > - crtc_state->master_transcoder = INVALID_TRANSCODER; > - crtc_state->hsw_workaround_pipe = INVALID_PIPE; > - crtc_state->output_format = INTEL_OUTPUT_FORMAT_INVALID; > - crtc_state->scaler_state.scaler_id = -1; > - crtc_state->mst_master_transcoder = INVALID_TRANSCODER; > -} > - > -static struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc) > -{ > - struct intel_crtc_state *crtc_state; > - > - crtc_state = kmalloc(sizeof(*crtc_state), GFP_KERNEL); > - > - if (crtc_state) > - intel_crtc_state_reset(crtc_state, crtc); > - > - return crtc_state; > -} > - > /* Returns the currently programmed mode of the given encoder. */ > struct drm_display_mode * > intel_encoder_current_mode(struct intel_encoder *encoder) > @@ -11975,14 +11486,6 @@ intel_encoder_current_mode(struct intel_encoder *encoder) > return mode; > } > > -static void intel_crtc_destroy(struct drm_crtc *crtc) > -{ > - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); > - > - drm_crtc_cleanup(crtc); > - kfree(intel_crtc); > -} > - > /** > * intel_wm_need_update - Check whether watermarks need updating > * @cur: current plane state > @@ -15186,17 +14689,6 @@ static int intel_atomic_prepare_commit(struct intel_atomic_state *state) > return 0; > } > > -u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc) > -{ > - struct drm_device *dev = crtc->base.dev; > - struct drm_vblank_crtc *vblank = &dev->vblank[drm_crtc_index(&crtc->base)]; > - > - if (!vblank->max_vblank_count) > - return (u32)drm_crtc_accurate_vblank_count(&crtc->base); > - > - return crtc->base.funcs->get_vblank_counter(&crtc->base); > -} > - > void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc, > struct intel_crtc_state *crtc_state) > { > @@ -16249,336 +15741,6 @@ void intel_plane_destroy(struct drm_plane *plane) > kfree(to_intel_plane(plane)); > } > > -static bool i8xx_plane_format_mod_supported(struct drm_plane *_plane, > - u32 format, u64 modifier) > -{ > - switch (modifier) { > - case DRM_FORMAT_MOD_LINEAR: > - case I915_FORMAT_MOD_X_TILED: > - break; > - default: > - return false; > - } > - > - switch (format) { > - case DRM_FORMAT_C8: > - case DRM_FORMAT_RGB565: > - case DRM_FORMAT_XRGB1555: > - case DRM_FORMAT_XRGB8888: > - return modifier == DRM_FORMAT_MOD_LINEAR || > - modifier == I915_FORMAT_MOD_X_TILED; > - default: > - return false; > - } > -} > - > -static bool i965_plane_format_mod_supported(struct drm_plane *_plane, > - u32 format, u64 modifier) > -{ > - switch (modifier) { > - case DRM_FORMAT_MOD_LINEAR: > - case I915_FORMAT_MOD_X_TILED: > - break; > - default: > - return false; > - } > - > - switch (format) { > - case DRM_FORMAT_C8: > - case DRM_FORMAT_RGB565: > - case DRM_FORMAT_XRGB8888: > - case DRM_FORMAT_XBGR8888: > - case DRM_FORMAT_ARGB8888: > - case DRM_FORMAT_ABGR8888: > - case DRM_FORMAT_XRGB2101010: > - case DRM_FORMAT_XBGR2101010: > - case DRM_FORMAT_ARGB2101010: > - case DRM_FORMAT_ABGR2101010: > - case DRM_FORMAT_XBGR16161616F: > - return modifier == DRM_FORMAT_MOD_LINEAR || > - modifier == I915_FORMAT_MOD_X_TILED; > - default: > - return false; > - } > -} > - > -static const struct drm_plane_funcs i965_plane_funcs = { > - .update_plane = drm_atomic_helper_update_plane, > - .disable_plane = drm_atomic_helper_disable_plane, > - .destroy = intel_plane_destroy, > - .atomic_duplicate_state = intel_plane_duplicate_state, > - .atomic_destroy_state = intel_plane_destroy_state, > - .format_mod_supported = i965_plane_format_mod_supported, > -}; > - > -static const struct drm_plane_funcs i8xx_plane_funcs = { > - .update_plane = drm_atomic_helper_update_plane, > - .disable_plane = drm_atomic_helper_disable_plane, > - .destroy = intel_plane_destroy, > - .atomic_duplicate_state = intel_plane_duplicate_state, > - .atomic_destroy_state = intel_plane_destroy_state, > - .format_mod_supported = i8xx_plane_format_mod_supported, > -}; > - > -static bool i9xx_plane_has_fbc(struct drm_i915_private *dev_priv, > - enum i9xx_plane_id i9xx_plane) > -{ > - if (!HAS_FBC(dev_priv)) > - return false; > - > - if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) > - return i9xx_plane == PLANE_A; /* tied to pipe A */ > - else if (IS_IVYBRIDGE(dev_priv)) > - return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B || > - i9xx_plane == PLANE_C; > - else if (INTEL_GEN(dev_priv) >= 4) > - return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B; > - else > - return i9xx_plane == PLANE_A; > -} > - > -static struct intel_plane * > -intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) > -{ > - struct intel_plane *plane; > - const struct drm_plane_funcs *plane_funcs; > - unsigned int supported_rotations; > - const u32 *formats; > - int num_formats; > - int ret, zpos; > - > - if (INTEL_GEN(dev_priv) >= 9) > - return skl_universal_plane_create(dev_priv, pipe, > - PLANE_PRIMARY); > - > - plane = intel_plane_alloc(); > - if (IS_ERR(plane)) > - return plane; > - > - plane->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) && INTEL_GEN(dev_priv) < 4 && > - INTEL_NUM_PIPES(dev_priv) == 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); > - > - plane->has_fbc = i9xx_plane_has_fbc(dev_priv, plane->i9xx_plane); > - if (plane->has_fbc) { > - struct intel_fbc *fbc = &dev_priv->fbc; > - > - fbc->possible_framebuffer_bits |= plane->frontbuffer_bit; > - } > - > - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { > - formats = vlv_primary_formats; > - num_formats = ARRAY_SIZE(vlv_primary_formats); > - } else if (INTEL_GEN(dev_priv) >= 4) { > - /* > - * WaFP16GammaEnabling:ivb > - * "Workaround : When using the 64-bit format, the plane > - * output on each color channel has one quarter amplitude. > - * It can be brought up to full amplitude by using pipe > - * gamma correction or pipe color space conversion to > - * multiply the plane output by four." > - * > - * There is no dedicated plane gamma for the primary plane, > - * and using the pipe gamma/csc could conflict with other > - * 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)) { > - formats = ivb_primary_formats; > - num_formats = ARRAY_SIZE(ivb_primary_formats); > - } else { > - formats = i965_primary_formats; > - num_formats = ARRAY_SIZE(i965_primary_formats); > - } > - } else { > - formats = i8xx_primary_formats; > - num_formats = ARRAY_SIZE(i8xx_primary_formats); > - } > - > - if (INTEL_GEN(dev_priv) >= 4) > - plane_funcs = &i965_plane_funcs; > - else > - plane_funcs = &i8xx_plane_funcs; > - > - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) > - plane->min_cdclk = vlv_plane_min_cdclk; > - else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) > - plane->min_cdclk = hsw_plane_min_cdclk; > - else if (IS_IVYBRIDGE(dev_priv)) > - plane->min_cdclk = ivb_plane_min_cdclk; > - else > - plane->min_cdclk = i9xx_plane_min_cdclk; > - > - plane->max_stride = i9xx_plane_max_stride; > - plane->update_plane = i9xx_update_plane; > - plane->disable_plane = i9xx_disable_plane; > - plane->get_hw_state = i9xx_plane_get_hw_state; > - plane->check_plane = i9xx_plane_check; > - > - if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) > - ret = drm_universal_plane_init(&dev_priv->drm, &plane->base, > - 0, plane_funcs, > - formats, num_formats, > - i9xx_format_modifiers, > - DRM_PLANE_TYPE_PRIMARY, > - "primary %c", pipe_name(pipe)); > - else > - ret = drm_universal_plane_init(&dev_priv->drm, &plane->base, > - 0, plane_funcs, > - formats, num_formats, > - i9xx_format_modifiers, > - DRM_PLANE_TYPE_PRIMARY, > - "plane %c", > - plane_name(plane->i9xx_plane)); > - if (ret) > - goto fail; > - > - if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) { > - supported_rotations = > - DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 | > - DRM_MODE_REFLECT_X; > - } else if (INTEL_GEN(dev_priv) >= 4) { > - supported_rotations = > - DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180; > - } else { > - supported_rotations = DRM_MODE_ROTATE_0; > - } > - > - if (INTEL_GEN(dev_priv) >= 4) > - drm_plane_create_rotation_property(&plane->base, > - DRM_MODE_ROTATE_0, > - supported_rotations); > - > - zpos = 0; > - drm_plane_create_zpos_immutable_property(&plane->base, zpos); > - > - drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs); > - > - return plane; > - > -fail: > - intel_plane_free(plane); > - > - return ERR_PTR(ret); > -} > - > -static int intel_crtc_late_register(struct drm_crtc *crtc) > -{ > - intel_crtc_debugfs_add(crtc); > - return 0; > -} > - > -#define INTEL_CRTC_FUNCS \ > - .gamma_set = drm_atomic_helper_legacy_gamma_set, \ > - .set_config = drm_atomic_helper_set_config, \ > - .destroy = intel_crtc_destroy, \ > - .page_flip = drm_atomic_helper_page_flip, \ > - .atomic_duplicate_state = intel_crtc_duplicate_state, \ > - .atomic_destroy_state = intel_crtc_destroy_state, \ > - .set_crc_source = intel_crtc_set_crc_source, \ > - .verify_crc_source = intel_crtc_verify_crc_source, \ > - .get_crc_sources = intel_crtc_get_crc_sources, \ > - .late_register = intel_crtc_late_register > - > -static const struct drm_crtc_funcs bdw_crtc_funcs = { > - INTEL_CRTC_FUNCS, > - > - .get_vblank_counter = g4x_get_vblank_counter, > - .enable_vblank = bdw_enable_vblank, > - .disable_vblank = bdw_disable_vblank, > - .get_vblank_timestamp = intel_crtc_get_vblank_timestamp, > -}; > - > -static const struct drm_crtc_funcs ilk_crtc_funcs = { > - INTEL_CRTC_FUNCS, > - > - .get_vblank_counter = g4x_get_vblank_counter, > - .enable_vblank = ilk_enable_vblank, > - .disable_vblank = ilk_disable_vblank, > - .get_vblank_timestamp = intel_crtc_get_vblank_timestamp, > -}; > - > -static const struct drm_crtc_funcs g4x_crtc_funcs = { > - INTEL_CRTC_FUNCS, > - > - .get_vblank_counter = g4x_get_vblank_counter, > - .enable_vblank = i965_enable_vblank, > - .disable_vblank = i965_disable_vblank, > - .get_vblank_timestamp = intel_crtc_get_vblank_timestamp, > -}; > - > -static const struct drm_crtc_funcs i965_crtc_funcs = { > - INTEL_CRTC_FUNCS, > - > - .get_vblank_counter = i915_get_vblank_counter, > - .enable_vblank = i965_enable_vblank, > - .disable_vblank = i965_disable_vblank, > - .get_vblank_timestamp = intel_crtc_get_vblank_timestamp, > -}; > - > -static const struct drm_crtc_funcs i915gm_crtc_funcs = { > - INTEL_CRTC_FUNCS, > - > - .get_vblank_counter = i915_get_vblank_counter, > - .enable_vblank = i915gm_enable_vblank, > - .disable_vblank = i915gm_disable_vblank, > - .get_vblank_timestamp = intel_crtc_get_vblank_timestamp, > -}; > - > -static const struct drm_crtc_funcs i915_crtc_funcs = { > - INTEL_CRTC_FUNCS, > - > - .get_vblank_counter = i915_get_vblank_counter, > - .enable_vblank = i8xx_enable_vblank, > - .disable_vblank = i8xx_disable_vblank, > - .get_vblank_timestamp = intel_crtc_get_vblank_timestamp, > -}; > - > -static const struct drm_crtc_funcs i8xx_crtc_funcs = { > - INTEL_CRTC_FUNCS, > - > - /* no hw vblank counter */ > - .enable_vblank = i8xx_enable_vblank, > - .disable_vblank = i8xx_disable_vblank, > - .get_vblank_timestamp = intel_crtc_get_vblank_timestamp, > -}; > - > -static struct intel_crtc *intel_crtc_alloc(void) > -{ > - struct intel_crtc_state *crtc_state; > - struct intel_crtc *crtc; > - > - crtc = kzalloc(sizeof(*crtc), GFP_KERNEL); > - if (!crtc) > - return ERR_PTR(-ENOMEM); > - > - crtc_state = intel_crtc_state_alloc(crtc); > - if (!crtc_state) { > - kfree(crtc); > - return ERR_PTR(-ENOMEM); > - } > - > - crtc->base.state = &crtc_state->uapi; > - crtc->config = crtc_state; > - > - return crtc; > -} > - > -static void intel_crtc_free(struct intel_crtc *crtc) > -{ > - intel_crtc_destroy_state(&crtc->base, crtc->base.state); > - kfree(crtc); > -} > - > static void intel_plane_possible_crtcs_init(struct drm_i915_private *dev_priv) > { > struct intel_plane *plane; > @@ -16591,100 +15753,6 @@ static void intel_plane_possible_crtcs_init(struct drm_i915_private *dev_priv) > } > } > > -static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe) > -{ > - struct intel_plane *primary, *cursor; > - const struct drm_crtc_funcs *funcs; > - struct intel_crtc *crtc; > - int sprite, ret; > - > - crtc = intel_crtc_alloc(); > - if (IS_ERR(crtc)) > - return PTR_ERR(crtc); > - > - crtc->pipe = pipe; > - crtc->num_scalers = RUNTIME_INFO(dev_priv)->num_scalers[pipe]; > - > - primary = intel_primary_plane_create(dev_priv, pipe); > - if (IS_ERR(primary)) { > - ret = PTR_ERR(primary); > - goto fail; > - } > - crtc->plane_ids_mask |= BIT(primary->id); > - > - for_each_sprite(dev_priv, pipe, sprite) { > - struct intel_plane *plane; > - > - plane = intel_sprite_plane_create(dev_priv, pipe, sprite); > - if (IS_ERR(plane)) { > - ret = PTR_ERR(plane); > - goto fail; > - } > - crtc->plane_ids_mask |= BIT(plane->id); > - } > - > - cursor = intel_cursor_plane_create(dev_priv, pipe); > - if (IS_ERR(cursor)) { > - ret = PTR_ERR(cursor); > - goto fail; > - } > - crtc->plane_ids_mask |= BIT(cursor->id); > - > - if (HAS_GMCH(dev_priv)) { > - if (IS_CHERRYVIEW(dev_priv) || > - IS_VALLEYVIEW(dev_priv) || IS_G4X(dev_priv)) > - funcs = &g4x_crtc_funcs; > - else if (IS_GEN(dev_priv, 4)) > - funcs = &i965_crtc_funcs; > - else if (IS_I945GM(dev_priv) || IS_I915GM(dev_priv)) > - funcs = &i915gm_crtc_funcs; > - else if (IS_GEN(dev_priv, 3)) > - funcs = &i915_crtc_funcs; > - else > - funcs = &i8xx_crtc_funcs; > - } else { > - if (INTEL_GEN(dev_priv) >= 8) > - funcs = &bdw_crtc_funcs; > - else > - funcs = &ilk_crtc_funcs; > - } > - > - ret = drm_crtc_init_with_planes(&dev_priv->drm, &crtc->base, > - &primary->base, &cursor->base, > - funcs, "pipe %c", pipe_name(pipe)); > - if (ret) > - goto fail; > - > - BUG_ON(pipe >= ARRAY_SIZE(dev_priv->pipe_to_crtc_mapping) || > - dev_priv->pipe_to_crtc_mapping[pipe] != NULL); > - dev_priv->pipe_to_crtc_mapping[pipe] = crtc; > - > - if (INTEL_GEN(dev_priv) < 9) { > - enum i9xx_plane_id i9xx_plane = primary->i9xx_plane; > - > - BUG_ON(i9xx_plane >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) || > - dev_priv->plane_to_crtc_mapping[i9xx_plane] != NULL); > - dev_priv->plane_to_crtc_mapping[i9xx_plane] = crtc; > - } > - > - if (INTEL_GEN(dev_priv) >= 10) > - drm_crtc_create_scaling_filter_property(&crtc->base, > - BIT(DRM_SCALING_FILTER_DEFAULT) | > - BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR)); > - > - intel_color_init(crtc); > - > - intel_crtc_crc_init(crtc); > - > - drm_WARN_ON(&dev_priv->drm, drm_crtc_index(&crtc->base) != crtc->pipe); > - > - return 0; > - > -fail: > - intel_crtc_free(crtc); > - > - return ret; > -} > > int intel_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data, > struct drm_file *file) > diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h > index f0a5bf69656f..0eba91d18e96 100644 > --- a/drivers/gpu/drm/i915/display/intel_display.h > +++ b/drivers/gpu/drm/i915/display/intel_display.h > @@ -659,6 +659,13 @@ struct intel_plane * > intel_cursor_plane_create(struct drm_i915_private *dev_priv, > enum pipe pipe); > > +/* crtc */ > +u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state); > +int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe); > +struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc); > +void intel_crtc_state_reset(struct intel_crtc_state *crtc_state, > + struct intel_crtc *crtc); > + > /* modesetting */ > void intel_modeset_init_hw(struct drm_i915_private *i915); > int intel_modeset_init_noirq(struct drm_i915_private *i915); > -- > 2.27.0 > > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/intel-gfx
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 98a35b939052..ffec257702af 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -196,6 +196,7 @@ i915-y += \ display/intel_color.o \ display/intel_combo_phy.o \ display/intel_connector.o \ + display/intel_crtc.o \ display/intel_csr.o \ display/intel_cursor.o \ display/intel_display.o \ diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c new file mode 100644 index 000000000000..75a79f18cee2 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_crtc.c @@ -0,0 +1,951 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2020 Intel Corporation + */ +#include <linux/kernel.h> +#include <linux/slab.h> + +#include <drm/drm_atomic_helper.h> +#include <drm/drm_fourcc.h> +#include <drm/drm_plane.h> +#include <drm/drm_plane_helper.h> + +#include "intel_atomic.h" +#include "intel_atomic_plane.h" +#include "intel_color.h" +#include "intel_display_debugfs.h" +#include "intel_display_types.h" +#include "intel_pipe_crc.h" +#include "intel_sprite.h" + +/* Primary plane formats for gen <= 3 */ +static const u32 i8xx_primary_formats[] = { + DRM_FORMAT_C8, + DRM_FORMAT_XRGB1555, + DRM_FORMAT_RGB565, + DRM_FORMAT_XRGB8888, +}; + +/* Primary plane formats for ivb (no fp16 due to hw issue) */ +static const u32 ivb_primary_formats[] = { + DRM_FORMAT_C8, + DRM_FORMAT_RGB565, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_XBGR8888, + DRM_FORMAT_XRGB2101010, + DRM_FORMAT_XBGR2101010, +}; + +/* Primary plane formats for gen >= 4, except ivb */ +static const u32 i965_primary_formats[] = { + DRM_FORMAT_C8, + DRM_FORMAT_RGB565, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_XBGR8888, + DRM_FORMAT_XRGB2101010, + DRM_FORMAT_XBGR2101010, + DRM_FORMAT_XBGR16161616F, +}; + +/* Primary plane formats for vlv/chv */ +static const u32 vlv_primary_formats[] = { + DRM_FORMAT_C8, + DRM_FORMAT_RGB565, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_XBGR8888, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_ABGR8888, + DRM_FORMAT_XRGB2101010, + DRM_FORMAT_XBGR2101010, + DRM_FORMAT_ARGB2101010, + DRM_FORMAT_ABGR2101010, + DRM_FORMAT_XBGR16161616F, +}; + +static const u64 i9xx_format_modifiers[] = { + I915_FORMAT_MOD_X_TILED, + DRM_FORMAT_MOD_LINEAR, + DRM_FORMAT_MOD_INVALID +}; + +static bool i8xx_plane_format_mod_supported(struct drm_plane *_plane, + u32 format, u64 modifier) +{ + switch (modifier) { + case DRM_FORMAT_MOD_LINEAR: + case I915_FORMAT_MOD_X_TILED: + break; + default: + return false; + } + + switch (format) { + case DRM_FORMAT_C8: + case DRM_FORMAT_RGB565: + case DRM_FORMAT_XRGB1555: + case DRM_FORMAT_XRGB8888: + return modifier == DRM_FORMAT_MOD_LINEAR || + modifier == I915_FORMAT_MOD_X_TILED; + default: + return false; + } +} + +static bool i965_plane_format_mod_supported(struct drm_plane *_plane, + u32 format, u64 modifier) +{ + switch (modifier) { + case DRM_FORMAT_MOD_LINEAR: + case I915_FORMAT_MOD_X_TILED: + break; + default: + return false; + } + + switch (format) { + case DRM_FORMAT_C8: + case DRM_FORMAT_RGB565: + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_ABGR8888: + case DRM_FORMAT_XRGB2101010: + case DRM_FORMAT_XBGR2101010: + case DRM_FORMAT_ARGB2101010: + case DRM_FORMAT_ABGR2101010: + case DRM_FORMAT_XBGR16161616F: + return modifier == DRM_FORMAT_MOD_LINEAR || + modifier == I915_FORMAT_MOD_X_TILED; + default: + return false; + } +} + +static bool i9xx_plane_has_fbc(struct drm_i915_private *dev_priv, + enum i9xx_plane_id i9xx_plane) +{ + if (!HAS_FBC(dev_priv)) + return false; + + if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) + return i9xx_plane == PLANE_A; /* tied to pipe A */ + else if (IS_IVYBRIDGE(dev_priv)) + return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B || + i9xx_plane == PLANE_C; + else if (INTEL_GEN(dev_priv) >= 4) + return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B; + else + return i9xx_plane == PLANE_A; +} + +static void assert_vblank_disabled(struct drm_crtc *crtc) +{ + if (I915_STATE_WARN_ON(drm_crtc_vblank_get(crtc) == 0)) + drm_crtc_vblank_put(crtc); +} + +u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc) +{ + struct drm_device *dev = crtc->base.dev; + struct drm_vblank_crtc *vblank = &dev->vblank[drm_crtc_index(&crtc->base)]; + + if (!vblank->max_vblank_count) + return (u32)drm_crtc_accurate_vblank_count(&crtc->base); + + return crtc->base.funcs->get_vblank_counter(&crtc->base); +} + +u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + u32 mode_flags = crtc->mode_flags; + + /* + * From Gen 11, In case of dsi cmd mode, frame counter wouldnt + * have updated at the beginning of TE, if we want to use + * the hw counter, then we would find it updated in only + * the next TE, hence switching to sw counter. + */ + if (mode_flags & (I915_MODE_FLAG_DSI_USE_TE0 | I915_MODE_FLAG_DSI_USE_TE1)) + return 0; + + /* + * On i965gm the hardware frame counter reads + * zero when the TV encoder is enabled :( + */ + if (IS_I965GM(dev_priv) && + (crtc_state->output_types & BIT(INTEL_OUTPUT_TVOUT))) + return 0; + + if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) + return 0xffffffff; /* full 32 bit counter */ + else if (INTEL_GEN(dev_priv) >= 3) + return 0xffffff; /* only 24 bits of frame count */ + else + return 0; /* Gen2 doesn't have a hardware frame counter */ +} + +void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + + assert_vblank_disabled(&crtc->base); + drm_crtc_set_max_vblank_count(&crtc->base, + intel_crtc_max_vblank_count(crtc_state)); + drm_crtc_vblank_on(&crtc->base); +} + +void intel_crtc_vblank_off(const struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + + drm_crtc_vblank_off(&crtc->base); + assert_vblank_disabled(&crtc->base); +} + +struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc) +{ + struct intel_crtc_state *crtc_state; + + crtc_state = kmalloc(sizeof(*crtc_state), GFP_KERNEL); + + if (crtc_state) + intel_crtc_state_reset(crtc_state, crtc); + + return crtc_state; +} + +void intel_crtc_state_reset(struct intel_crtc_state *crtc_state, + struct intel_crtc *crtc) +{ + memset(crtc_state, 0, sizeof(*crtc_state)); + + __drm_atomic_helper_crtc_state_reset(&crtc_state->uapi, &crtc->base); + + crtc_state->cpu_transcoder = INVALID_TRANSCODER; + crtc_state->master_transcoder = INVALID_TRANSCODER; + crtc_state->hsw_workaround_pipe = INVALID_PIPE; + crtc_state->output_format = INTEL_OUTPUT_FORMAT_INVALID; + crtc_state->scaler_state.scaler_id = -1; + crtc_state->mst_master_transcoder = INVALID_TRANSCODER; +} + +static bool i9xx_plane_has_windowing(struct intel_plane *plane) +{ + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; + + if (IS_CHERRYVIEW(dev_priv)) + return i9xx_plane == PLANE_B; + else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) + return false; + else if (IS_GEN(dev_priv, 4)) + return i9xx_plane == PLANE_C; + else + return i9xx_plane == PLANE_B || + i9xx_plane == PLANE_C; +} + +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); + const struct drm_framebuffer *fb = plane_state->hw.fb; + unsigned int rotation = plane_state->hw.rotation; + u32 dspcntr; + + dspcntr = DISPLAY_PLANE_ENABLE; + + if (IS_G4X(dev_priv) || IS_GEN(dev_priv, 5) || + IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv)) + dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; + + switch (fb->format->format) { + case DRM_FORMAT_C8: + dspcntr |= DISPPLANE_8BPP; + break; + case DRM_FORMAT_XRGB1555: + dspcntr |= DISPPLANE_BGRX555; + break; + case DRM_FORMAT_ARGB1555: + dspcntr |= DISPPLANE_BGRA555; + break; + case DRM_FORMAT_RGB565: + dspcntr |= DISPPLANE_BGRX565; + break; + case DRM_FORMAT_XRGB8888: + dspcntr |= DISPPLANE_BGRX888; + break; + case DRM_FORMAT_XBGR8888: + dspcntr |= DISPPLANE_RGBX888; + break; + case DRM_FORMAT_ARGB8888: + dspcntr |= DISPPLANE_BGRA888; + break; + case DRM_FORMAT_ABGR8888: + dspcntr |= DISPPLANE_RGBA888; + break; + case DRM_FORMAT_XRGB2101010: + dspcntr |= DISPPLANE_BGRX101010; + break; + case DRM_FORMAT_XBGR2101010: + dspcntr |= DISPPLANE_RGBX101010; + break; + case DRM_FORMAT_ARGB2101010: + dspcntr |= DISPPLANE_BGRA101010; + break; + case DRM_FORMAT_ABGR2101010: + dspcntr |= DISPPLANE_RGBA101010; + break; + case DRM_FORMAT_XBGR16161616F: + dspcntr |= DISPPLANE_RGBX161616; + break; + default: + MISSING_CASE(fb->format->format); + return 0; + } + + if (INTEL_GEN(dev_priv) >= 4 && + fb->modifier == I915_FORMAT_MOD_X_TILED) + dspcntr |= DISPPLANE_TILED; + + if (rotation & DRM_MODE_ROTATE_180) + dspcntr |= DISPPLANE_ROTATE_180; + + if (rotation & DRM_MODE_REFLECT_X) + dspcntr |= DISPPLANE_MIRROR; + + return dspcntr; +} + +static int +i9xx_plane_check(struct intel_crtc_state *crtc_state, + struct intel_plane_state *plane_state) +{ + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); + int ret; + + ret = chv_plane_check_rotation(plane_state); + if (ret) + return ret; + + ret = intel_atomic_plane_check_clipping(plane_state, crtc_state, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + i9xx_plane_has_windowing(plane)); + if (ret) + return ret; + + ret = i9xx_check_plane_surface(plane_state); + if (ret) + return ret; + + if (!plane_state->uapi.visible) + return 0; + + ret = intel_plane_check_src_coordinates(plane_state); + if (ret) + return ret; + + plane_state->ctl = i9xx_plane_ctl(crtc_state, plane_state); + + return 0; +} + +static u32 i9xx_plane_ctl_crtc(const struct intel_crtc_state *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) + dspcntr |= DISPPLANE_GAMMA_ENABLE; + + if (crtc_state->csc_enable) + dspcntr |= DISPPLANE_PIPE_CSC_ENABLE; + + if (INTEL_GEN(dev_priv) < 5) + dspcntr |= DISPPLANE_SEL_PIPE(crtc->pipe); + + return dspcntr; +} + +static void i9xx_plane_ratio(const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state, + unsigned int *num, unsigned int *den) +{ + const struct drm_framebuffer *fb = plane_state->hw.fb; + unsigned int cpp = fb->format->cpp[0]; + + /* + * g4x bspec says 64bpp pixel rate can't exceed 80% + * of cdclk when the sprite plane is enabled on the + * same pipe. ilk/snb bspec says 64bpp pixel rate is + * never allowed to exceed 80% of cdclk. Let's just go + * with the ilk/snb limit always. + */ + if (cpp == 8) { + *num = 10; + *den = 8; + } else { + *num = 1; + *den = 1; + } +} + +static int i9xx_plane_min_cdclk(const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) +{ + unsigned int pixel_rate; + unsigned int num, den; + + /* + * Note that crtc_state->pixel_rate accounts for both + * horizontal and vertical panel fitter downscaling factors. + * Pre-HSW bspec tells us to only consider the horizontal + * downscaling factor here. We ignore that and just consider + * both for simplicity. + */ + pixel_rate = crtc_state->pixel_rate; + + i9xx_plane_ratio(crtc_state, plane_state, &num, &den); + + /* two pixels per clock with double wide pipe */ + if (crtc_state->double_wide) + den *= 2; + + return DIV_ROUND_UP(pixel_rate * num, den); +} + +static void i9xx_update_plane(struct intel_plane *plane, + 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); + enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; + u32 linear_offset; + int x = plane_state->color_plane[0].x; + int y = plane_state->color_plane[0].y; + 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); + unsigned long irqflags; + u32 dspaddr_offset; + u32 dspcntr; + + dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state); + + linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); + + if (INTEL_GEN(dev_priv) >= 4) + dspaddr_offset = plane_state->color_plane[0].offset; + else + dspaddr_offset = linear_offset; + + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + + intel_de_write_fw(dev_priv, DSPSTRIDE(i9xx_plane), + plane_state->color_plane[0].stride); + + if (INTEL_GEN(dev_priv) < 4) { + /* + * PLANE_A doesn't actually have a full window + * generator but let's assume we still need to + * program whatever is there. + */ + intel_de_write_fw(dev_priv, DSPPOS(i9xx_plane), + (crtc_y << 16) | crtc_x); + intel_de_write_fw(dev_priv, DSPSIZE(i9xx_plane), + ((crtc_h - 1) << 16) | (crtc_w - 1)); + } else if (IS_CHERRYVIEW(dev_priv) && i9xx_plane == PLANE_B) { + intel_de_write_fw(dev_priv, PRIMPOS(i9xx_plane), + (crtc_y << 16) | crtc_x); + intel_de_write_fw(dev_priv, PRIMSIZE(i9xx_plane), + ((crtc_h - 1) << 16) | (crtc_w - 1)); + intel_de_write_fw(dev_priv, PRIMCNSTALPHA(i9xx_plane), 0); + } + + if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { + intel_de_write_fw(dev_priv, DSPOFFSET(i9xx_plane), + (y << 16) | x); + } else if (INTEL_GEN(dev_priv) >= 4) { + intel_de_write_fw(dev_priv, DSPLINOFF(i9xx_plane), + linear_offset); + intel_de_write_fw(dev_priv, DSPTILEOFF(i9xx_plane), + (y << 16) | x); + } + + /* + * The control register self-arms if the plane was previously + * 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(i9xx_plane), dspcntr); + if (INTEL_GEN(dev_priv) >= 4) + intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), + intel_plane_ggtt_offset(plane_state) + dspaddr_offset); + else + intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), + intel_plane_ggtt_offset(plane_state) + dspaddr_offset); + + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); +} + +static void i9xx_disable_plane(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; + unsigned long irqflags; + u32 dspcntr; + + /* + * DSPCNTR pipe gamma enable on g4x+ and pipe csc + * enable on ilk+ affect the pipe bottom color as + * well, so we must configure them even if the plane + * is disabled. + * + * On pre-g4x there is no way to gamma correct the + * pipe bottom color but we'll keep on doing this + * anyway so that the crtc state readout works correctly. + */ + dspcntr = i9xx_plane_ctl_crtc(crtc_state); + + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + + intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr); + if (INTEL_GEN(dev_priv) >= 4) + intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), 0); + else + intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), 0); + + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); +} + +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); + enum intel_display_power_domain power_domain; + enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; + intel_wakeref_t wakeref; + bool ret; + u32 val; + + /* + * Not 100% correct for planes that can move between pipes, + * but that's only the case for gen2-4 which don't have any + * display power wells. + */ + power_domain = POWER_DOMAIN_PIPE(plane->pipe); + wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain); + if (!wakeref) + return false; + + val = intel_de_read(dev_priv, DSPCNTR(i9xx_plane)); + + ret = val & DISPLAY_PLANE_ENABLE; + + if (INTEL_GEN(dev_priv) >= 5) + *pipe = plane->pipe; + else + *pipe = (val & DISPPLANE_SEL_PIPE_MASK) >> + DISPPLANE_SEL_PIPE_SHIFT; + + intel_display_power_put(dev_priv, power_domain, wakeref); + + return ret; +} + +unsigned int +i9xx_plane_max_stride(struct intel_plane *plane, + u32 pixel_format, u64 modifier, + unsigned int rotation) +{ + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + + if (!HAS_GMCH(dev_priv)) { + return 32*1024; + } else if (INTEL_GEN(dev_priv) >= 4) { + if (modifier == I915_FORMAT_MOD_X_TILED) + return 16*1024; + else + return 32*1024; + } else if (INTEL_GEN(dev_priv) >= 3) { + if (modifier == I915_FORMAT_MOD_X_TILED) + return 8*1024; + else + return 16*1024; + } else { + if (plane->i9xx_plane == PLANE_C) + return 4*1024; + else + return 8*1024; + } +} + +static const struct drm_plane_funcs i965_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = intel_plane_destroy, + .atomic_duplicate_state = intel_plane_duplicate_state, + .atomic_destroy_state = intel_plane_destroy_state, + .format_mod_supported = i965_plane_format_mod_supported, +}; + +static const struct drm_plane_funcs i8xx_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = intel_plane_destroy, + .atomic_duplicate_state = intel_plane_duplicate_state, + .atomic_destroy_state = intel_plane_destroy_state, + .format_mod_supported = i8xx_plane_format_mod_supported, +}; + +static struct intel_plane * +intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) +{ + struct intel_plane *plane; + const struct drm_plane_funcs *plane_funcs; + unsigned int supported_rotations; + const u32 *formats; + int num_formats; + int ret, zpos; + + if (INTEL_GEN(dev_priv) >= 9) + return skl_universal_plane_create(dev_priv, pipe, + PLANE_PRIMARY); + + plane = intel_plane_alloc(); + if (IS_ERR(plane)) + return plane; + + plane->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) && INTEL_GEN(dev_priv) < 4 && + INTEL_NUM_PIPES(dev_priv) == 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); + + plane->has_fbc = i9xx_plane_has_fbc(dev_priv, plane->i9xx_plane); + if (plane->has_fbc) { + struct intel_fbc *fbc = &dev_priv->fbc; + + fbc->possible_framebuffer_bits |= plane->frontbuffer_bit; + } + + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { + formats = vlv_primary_formats; + num_formats = ARRAY_SIZE(vlv_primary_formats); + } else if (INTEL_GEN(dev_priv) >= 4) { + /* + * WaFP16GammaEnabling:ivb + * "Workaround : When using the 64-bit format, the plane + * output on each color channel has one quarter amplitude. + * It can be brought up to full amplitude by using pipe + * gamma correction or pipe color space conversion to + * multiply the plane output by four." + * + * There is no dedicated plane gamma for the primary plane, + * and using the pipe gamma/csc could conflict with other + * 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)) { + formats = ivb_primary_formats; + num_formats = ARRAY_SIZE(ivb_primary_formats); + } else { + formats = i965_primary_formats; + num_formats = ARRAY_SIZE(i965_primary_formats); + } + } else { + formats = i8xx_primary_formats; + num_formats = ARRAY_SIZE(i8xx_primary_formats); + } + + if (INTEL_GEN(dev_priv) >= 4) + plane_funcs = &i965_plane_funcs; + else + plane_funcs = &i8xx_plane_funcs; + + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) + plane->min_cdclk = vlv_plane_min_cdclk; + else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) + plane->min_cdclk = hsw_plane_min_cdclk; + else if (IS_IVYBRIDGE(dev_priv)) + plane->min_cdclk = ivb_plane_min_cdclk; + else + plane->min_cdclk = i9xx_plane_min_cdclk; + + plane->max_stride = i9xx_plane_max_stride; + plane->update_plane = i9xx_update_plane; + plane->disable_plane = i9xx_disable_plane; + plane->get_hw_state = i9xx_plane_get_hw_state; + plane->check_plane = i9xx_plane_check; + + if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) + ret = drm_universal_plane_init(&dev_priv->drm, &plane->base, + 0, plane_funcs, + formats, num_formats, + i9xx_format_modifiers, + DRM_PLANE_TYPE_PRIMARY, + "primary %c", pipe_name(pipe)); + else + ret = drm_universal_plane_init(&dev_priv->drm, &plane->base, + 0, plane_funcs, + formats, num_formats, + i9xx_format_modifiers, + DRM_PLANE_TYPE_PRIMARY, + "plane %c", + plane_name(plane->i9xx_plane)); + if (ret) + goto fail; + + if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) { + supported_rotations = + DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 | + DRM_MODE_REFLECT_X; + } else if (INTEL_GEN(dev_priv) >= 4) { + supported_rotations = + DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180; + } else { + supported_rotations = DRM_MODE_ROTATE_0; + } + + if (INTEL_GEN(dev_priv) >= 4) + drm_plane_create_rotation_property(&plane->base, + DRM_MODE_ROTATE_0, + supported_rotations); + + zpos = 0; + drm_plane_create_zpos_immutable_property(&plane->base, zpos); + + drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs); + + return plane; + +fail: + intel_plane_free(plane); + + return ERR_PTR(ret); +} + +static struct intel_crtc *intel_crtc_alloc(void) +{ + struct intel_crtc_state *crtc_state; + struct intel_crtc *crtc; + + crtc = kzalloc(sizeof(*crtc), GFP_KERNEL); + if (!crtc) + return ERR_PTR(-ENOMEM); + + crtc_state = intel_crtc_state_alloc(crtc); + if (!crtc_state) { + kfree(crtc); + return ERR_PTR(-ENOMEM); + } + + crtc->base.state = &crtc_state->uapi; + crtc->config = crtc_state; + + return crtc; +} + +static void intel_crtc_free(struct intel_crtc *crtc) +{ + intel_crtc_destroy_state(&crtc->base, crtc->base.state); + kfree(crtc); +} + +static void intel_crtc_destroy(struct drm_crtc *crtc) +{ + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + + drm_crtc_cleanup(crtc); + kfree(intel_crtc); +} + +static int intel_crtc_late_register(struct drm_crtc *crtc) +{ + intel_crtc_debugfs_add(crtc); + return 0; +} + +#define INTEL_CRTC_FUNCS \ + .gamma_set = drm_atomic_helper_legacy_gamma_set, \ + .set_config = drm_atomic_helper_set_config, \ + .destroy = intel_crtc_destroy, \ + .page_flip = drm_atomic_helper_page_flip, \ + .atomic_duplicate_state = intel_crtc_duplicate_state, \ + .atomic_destroy_state = intel_crtc_destroy_state, \ + .set_crc_source = intel_crtc_set_crc_source, \ + .verify_crc_source = intel_crtc_verify_crc_source, \ + .get_crc_sources = intel_crtc_get_crc_sources, \ + .late_register = intel_crtc_late_register + +static const struct drm_crtc_funcs bdw_crtc_funcs = { + INTEL_CRTC_FUNCS, + + .get_vblank_counter = g4x_get_vblank_counter, + .enable_vblank = bdw_enable_vblank, + .disable_vblank = bdw_disable_vblank, + .get_vblank_timestamp = intel_crtc_get_vblank_timestamp, +}; + +static const struct drm_crtc_funcs ilk_crtc_funcs = { + INTEL_CRTC_FUNCS, + + .get_vblank_counter = g4x_get_vblank_counter, + .enable_vblank = ilk_enable_vblank, + .disable_vblank = ilk_disable_vblank, + .get_vblank_timestamp = intel_crtc_get_vblank_timestamp, +}; + +static const struct drm_crtc_funcs g4x_crtc_funcs = { + INTEL_CRTC_FUNCS, + + .get_vblank_counter = g4x_get_vblank_counter, + .enable_vblank = i965_enable_vblank, + .disable_vblank = i965_disable_vblank, + .get_vblank_timestamp = intel_crtc_get_vblank_timestamp, +}; + +static const struct drm_crtc_funcs i965_crtc_funcs = { + INTEL_CRTC_FUNCS, + + .get_vblank_counter = i915_get_vblank_counter, + .enable_vblank = i965_enable_vblank, + .disable_vblank = i965_disable_vblank, + .get_vblank_timestamp = intel_crtc_get_vblank_timestamp, +}; + +static const struct drm_crtc_funcs i915gm_crtc_funcs = { + INTEL_CRTC_FUNCS, + + .get_vblank_counter = i915_get_vblank_counter, + .enable_vblank = i915gm_enable_vblank, + .disable_vblank = i915gm_disable_vblank, + .get_vblank_timestamp = intel_crtc_get_vblank_timestamp, +}; + +static const struct drm_crtc_funcs i915_crtc_funcs = { + INTEL_CRTC_FUNCS, + + .get_vblank_counter = i915_get_vblank_counter, + .enable_vblank = i8xx_enable_vblank, + .disable_vblank = i8xx_disable_vblank, + .get_vblank_timestamp = intel_crtc_get_vblank_timestamp, +}; + +static const struct drm_crtc_funcs i8xx_crtc_funcs = { + INTEL_CRTC_FUNCS, + + /* no hw vblank counter */ + .enable_vblank = i8xx_enable_vblank, + .disable_vblank = i8xx_disable_vblank, + .get_vblank_timestamp = intel_crtc_get_vblank_timestamp, +}; + +int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe) +{ + struct intel_plane *primary, *cursor; + const struct drm_crtc_funcs *funcs; + struct intel_crtc *crtc; + int sprite, ret; + + crtc = intel_crtc_alloc(); + if (IS_ERR(crtc)) + return PTR_ERR(crtc); + + crtc->pipe = pipe; + crtc->num_scalers = RUNTIME_INFO(dev_priv)->num_scalers[pipe]; + + primary = intel_primary_plane_create(dev_priv, pipe); + if (IS_ERR(primary)) { + ret = PTR_ERR(primary); + goto fail; + } + crtc->plane_ids_mask |= BIT(primary->id); + + for_each_sprite(dev_priv, pipe, sprite) { + struct intel_plane *plane; + + plane = intel_sprite_plane_create(dev_priv, pipe, sprite); + if (IS_ERR(plane)) { + ret = PTR_ERR(plane); + goto fail; + } + crtc->plane_ids_mask |= BIT(plane->id); + } + + cursor = intel_cursor_plane_create(dev_priv, pipe); + if (IS_ERR(cursor)) { + ret = PTR_ERR(cursor); + goto fail; + } + crtc->plane_ids_mask |= BIT(cursor->id); + + if (HAS_GMCH(dev_priv)) { + if (IS_CHERRYVIEW(dev_priv) || + IS_VALLEYVIEW(dev_priv) || IS_G4X(dev_priv)) + funcs = &g4x_crtc_funcs; + else if (IS_GEN(dev_priv, 4)) + funcs = &i965_crtc_funcs; + else if (IS_I945GM(dev_priv) || IS_I915GM(dev_priv)) + funcs = &i915gm_crtc_funcs; + else if (IS_GEN(dev_priv, 3)) + funcs = &i915_crtc_funcs; + else + funcs = &i8xx_crtc_funcs; + } else { + if (INTEL_GEN(dev_priv) >= 8) + funcs = &bdw_crtc_funcs; + else + funcs = &ilk_crtc_funcs; + } + + ret = drm_crtc_init_with_planes(&dev_priv->drm, &crtc->base, + &primary->base, &cursor->base, + funcs, "pipe %c", pipe_name(pipe)); + if (ret) + goto fail; + + BUG_ON(pipe >= ARRAY_SIZE(dev_priv->pipe_to_crtc_mapping) || + dev_priv->pipe_to_crtc_mapping[pipe] != NULL); + dev_priv->pipe_to_crtc_mapping[pipe] = crtc; + + if (INTEL_GEN(dev_priv) < 9) { + enum i9xx_plane_id i9xx_plane = primary->i9xx_plane; + + BUG_ON(i9xx_plane >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) || + dev_priv->plane_to_crtc_mapping[i9xx_plane] != NULL); + dev_priv->plane_to_crtc_mapping[i9xx_plane] = crtc; + } + + if (INTEL_GEN(dev_priv) >= 10) + drm_crtc_create_scaling_filter_property(&crtc->base, + BIT(DRM_SCALING_FILTER_DEFAULT) | + BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR)); + + intel_color_init(crtc); + + intel_crtc_crc_init(crtc); + + drm_WARN_ON(&dev_priv->drm, drm_crtc_index(&crtc->base) != crtc->pipe); + + return 0; + +fail: + intel_crtc_free(crtc); + + return ret; +} diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 722a1cf61941..2507a72ee249 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -87,56 +87,6 @@ #include "intel_tc.h" #include "intel_vga.h" -/* Primary plane formats for gen <= 3 */ -static const u32 i8xx_primary_formats[] = { - DRM_FORMAT_C8, - DRM_FORMAT_XRGB1555, - DRM_FORMAT_RGB565, - DRM_FORMAT_XRGB8888, -}; - -/* Primary plane formats for ivb (no fp16 due to hw issue) */ -static const u32 ivb_primary_formats[] = { - DRM_FORMAT_C8, - DRM_FORMAT_RGB565, - DRM_FORMAT_XRGB8888, - DRM_FORMAT_XBGR8888, - DRM_FORMAT_XRGB2101010, - DRM_FORMAT_XBGR2101010, -}; - -/* Primary plane formats for gen >= 4, except ivb */ -static const u32 i965_primary_formats[] = { - DRM_FORMAT_C8, - DRM_FORMAT_RGB565, - DRM_FORMAT_XRGB8888, - DRM_FORMAT_XBGR8888, - DRM_FORMAT_XRGB2101010, - DRM_FORMAT_XBGR2101010, - DRM_FORMAT_XBGR16161616F, -}; - -/* Primary plane formats for vlv/chv */ -static const u32 vlv_primary_formats[] = { - DRM_FORMAT_C8, - DRM_FORMAT_RGB565, - DRM_FORMAT_XRGB8888, - DRM_FORMAT_XBGR8888, - DRM_FORMAT_ARGB8888, - DRM_FORMAT_ABGR8888, - DRM_FORMAT_XRGB2101010, - DRM_FORMAT_XBGR2101010, - DRM_FORMAT_ARGB2101010, - DRM_FORMAT_ABGR2101010, - DRM_FORMAT_XBGR16161616F, -}; - -static const u64 i9xx_format_modifiers[] = { - I915_FORMAT_MOD_X_TILED, - DRM_FORMAT_MOD_LINEAR, - DRM_FORMAT_MOD_INVALID -}; - static void i9xx_crtc_clock_get(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config); static void ilk_pch_clock_get(struct intel_crtc *crtc, @@ -162,7 +112,6 @@ static void skl_pfit_enable(const struct intel_crtc_state *crtc_state); static void ilk_pfit_enable(const struct intel_crtc_state *crtc_state); static void intel_modeset_setup_hw_state(struct drm_device *dev, struct drm_modeset_acquire_ctx *ctx); -static struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc); struct intel_limit { struct { @@ -1301,12 +1250,6 @@ static void assert_planes_disabled(struct intel_crtc *crtc) assert_plane_disabled(plane); } -static void assert_vblank_disabled(struct drm_crtc *crtc) -{ - if (I915_STATE_WARN_ON(drm_crtc_vblank_get(crtc) == 0)) - drm_crtc_vblank_put(crtc); -} - void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv, enum pipe pipe) { @@ -1791,55 +1734,6 @@ enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc) return crtc->pipe; } -static u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state) -{ - struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - u32 mode_flags = crtc->mode_flags; - - /* - * From Gen 11, In case of dsi cmd mode, frame counter wouldnt - * have updated at the beginning of TE, if we want to use - * the hw counter, then we would find it updated in only - * the next TE, hence switching to sw counter. - */ - if (mode_flags & (I915_MODE_FLAG_DSI_USE_TE0 | I915_MODE_FLAG_DSI_USE_TE1)) - return 0; - - /* - * On i965gm the hardware frame counter reads - * zero when the TV encoder is enabled :( - */ - if (IS_I965GM(dev_priv) && - (crtc_state->output_types & BIT(INTEL_OUTPUT_TVOUT))) - return 0; - - if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) - return 0xffffffff; /* full 32 bit counter */ - else if (INTEL_GEN(dev_priv) >= 3) - return 0xffffff; /* only 24 bits of frame count */ - else - return 0; /* Gen2 doesn't have a hardware frame counter */ -} - -void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state) -{ - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - - assert_vblank_disabled(&crtc->base); - drm_crtc_set_max_vblank_count(&crtc->base, - intel_crtc_max_vblank_count(crtc_state)); - drm_crtc_vblank_on(&crtc->base); -} - -void intel_crtc_vblank_off(const struct intel_crtc_state *crtc_state) -{ - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - - drm_crtc_vblank_off(&crtc->base); - assert_vblank_disabled(&crtc->base); -} - void intel_enable_pipe(const struct intel_crtc_state *new_crtc_state) { struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); @@ -4046,171 +3940,6 @@ int skl_check_plane_surface(struct intel_plane_state *plane_state) return 0; } -static void i9xx_plane_ratio(const struct intel_crtc_state *crtc_state, - const struct intel_plane_state *plane_state, - unsigned int *num, unsigned int *den) -{ - const struct drm_framebuffer *fb = plane_state->hw.fb; - unsigned int cpp = fb->format->cpp[0]; - - /* - * g4x bspec says 64bpp pixel rate can't exceed 80% - * of cdclk when the sprite plane is enabled on the - * same pipe. ilk/snb bspec says 64bpp pixel rate is - * never allowed to exceed 80% of cdclk. Let's just go - * with the ilk/snb limit always. - */ - if (cpp == 8) { - *num = 10; - *den = 8; - } else { - *num = 1; - *den = 1; - } -} - -static int i9xx_plane_min_cdclk(const struct intel_crtc_state *crtc_state, - const struct intel_plane_state *plane_state) -{ - unsigned int pixel_rate; - unsigned int num, den; - - /* - * Note that crtc_state->pixel_rate accounts for both - * horizontal and vertical panel fitter downscaling factors. - * Pre-HSW bspec tells us to only consider the horizontal - * downscaling factor here. We ignore that and just consider - * both for simplicity. - */ - pixel_rate = crtc_state->pixel_rate; - - i9xx_plane_ratio(crtc_state, plane_state, &num, &den); - - /* two pixels per clock with double wide pipe */ - if (crtc_state->double_wide) - den *= 2; - - return DIV_ROUND_UP(pixel_rate * num, den); -} - -unsigned int -i9xx_plane_max_stride(struct intel_plane *plane, - u32 pixel_format, u64 modifier, - unsigned int rotation) -{ - struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - - if (!HAS_GMCH(dev_priv)) { - return 32*1024; - } else if (INTEL_GEN(dev_priv) >= 4) { - if (modifier == I915_FORMAT_MOD_X_TILED) - return 16*1024; - else - return 32*1024; - } else if (INTEL_GEN(dev_priv) >= 3) { - if (modifier == I915_FORMAT_MOD_X_TILED) - return 8*1024; - else - return 16*1024; - } else { - if (plane->i9xx_plane == PLANE_C) - return 4*1024; - else - return 8*1024; - } -} - -static u32 i9xx_plane_ctl_crtc(const struct intel_crtc_state *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) - dspcntr |= DISPPLANE_GAMMA_ENABLE; - - if (crtc_state->csc_enable) - dspcntr |= DISPPLANE_PIPE_CSC_ENABLE; - - if (INTEL_GEN(dev_priv) < 5) - dspcntr |= DISPPLANE_SEL_PIPE(crtc->pipe); - - return dspcntr; -} - -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); - const struct drm_framebuffer *fb = plane_state->hw.fb; - unsigned int rotation = plane_state->hw.rotation; - u32 dspcntr; - - dspcntr = DISPLAY_PLANE_ENABLE; - - if (IS_G4X(dev_priv) || IS_GEN(dev_priv, 5) || - IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv)) - dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; - - switch (fb->format->format) { - case DRM_FORMAT_C8: - dspcntr |= DISPPLANE_8BPP; - break; - case DRM_FORMAT_XRGB1555: - dspcntr |= DISPPLANE_BGRX555; - break; - case DRM_FORMAT_ARGB1555: - dspcntr |= DISPPLANE_BGRA555; - break; - case DRM_FORMAT_RGB565: - dspcntr |= DISPPLANE_BGRX565; - break; - case DRM_FORMAT_XRGB8888: - dspcntr |= DISPPLANE_BGRX888; - break; - case DRM_FORMAT_XBGR8888: - dspcntr |= DISPPLANE_RGBX888; - break; - case DRM_FORMAT_ARGB8888: - dspcntr |= DISPPLANE_BGRA888; - break; - case DRM_FORMAT_ABGR8888: - dspcntr |= DISPPLANE_RGBA888; - break; - case DRM_FORMAT_XRGB2101010: - dspcntr |= DISPPLANE_BGRX101010; - break; - case DRM_FORMAT_XBGR2101010: - dspcntr |= DISPPLANE_RGBX101010; - break; - case DRM_FORMAT_ARGB2101010: - dspcntr |= DISPPLANE_BGRA101010; - break; - case DRM_FORMAT_ABGR2101010: - dspcntr |= DISPPLANE_RGBA101010; - break; - case DRM_FORMAT_XBGR16161616F: - dspcntr |= DISPPLANE_RGBX161616; - break; - default: - MISSING_CASE(fb->format->format); - return 0; - } - - if (INTEL_GEN(dev_priv) >= 4 && - fb->modifier == I915_FORMAT_MOD_X_TILED) - dspcntr |= DISPPLANE_TILED; - - if (rotation & DRM_MODE_ROTATE_180) - dspcntr |= DISPPLANE_ROTATE_180; - - if (rotation & DRM_MODE_REFLECT_X) - dspcntr |= DISPPLANE_MIRROR; - - return dspcntr; -} - int i9xx_check_plane_surface(struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = @@ -4271,197 +4000,6 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state) return 0; } -static bool i9xx_plane_has_windowing(struct intel_plane *plane) -{ - struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; - - if (IS_CHERRYVIEW(dev_priv)) - return i9xx_plane == PLANE_B; - else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) - return false; - else if (IS_GEN(dev_priv, 4)) - return i9xx_plane == PLANE_C; - else - return i9xx_plane == PLANE_B || - i9xx_plane == PLANE_C; -} - -static int -i9xx_plane_check(struct intel_crtc_state *crtc_state, - struct intel_plane_state *plane_state) -{ - struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); - int ret; - - ret = chv_plane_check_rotation(plane_state); - if (ret) - return ret; - - ret = intel_atomic_plane_check_clipping(plane_state, crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, - i9xx_plane_has_windowing(plane)); - if (ret) - return ret; - - ret = i9xx_check_plane_surface(plane_state); - if (ret) - return ret; - - if (!plane_state->uapi.visible) - return 0; - - ret = intel_plane_check_src_coordinates(plane_state); - if (ret) - return ret; - - plane_state->ctl = i9xx_plane_ctl(crtc_state, plane_state); - - return 0; -} - -static void i9xx_update_plane(struct intel_plane *plane, - 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); - enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; - u32 linear_offset; - int x = plane_state->color_plane[0].x; - int y = plane_state->color_plane[0].y; - 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); - unsigned long irqflags; - u32 dspaddr_offset; - u32 dspcntr; - - dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state); - - linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); - - if (INTEL_GEN(dev_priv) >= 4) - dspaddr_offset = plane_state->color_plane[0].offset; - else - dspaddr_offset = linear_offset; - - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - - intel_de_write_fw(dev_priv, DSPSTRIDE(i9xx_plane), - plane_state->color_plane[0].stride); - - if (INTEL_GEN(dev_priv) < 4) { - /* - * PLANE_A doesn't actually have a full window - * generator but let's assume we still need to - * program whatever is there. - */ - intel_de_write_fw(dev_priv, DSPPOS(i9xx_plane), - (crtc_y << 16) | crtc_x); - intel_de_write_fw(dev_priv, DSPSIZE(i9xx_plane), - ((crtc_h - 1) << 16) | (crtc_w - 1)); - } else if (IS_CHERRYVIEW(dev_priv) && i9xx_plane == PLANE_B) { - intel_de_write_fw(dev_priv, PRIMPOS(i9xx_plane), - (crtc_y << 16) | crtc_x); - intel_de_write_fw(dev_priv, PRIMSIZE(i9xx_plane), - ((crtc_h - 1) << 16) | (crtc_w - 1)); - intel_de_write_fw(dev_priv, PRIMCNSTALPHA(i9xx_plane), 0); - } - - if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { - intel_de_write_fw(dev_priv, DSPOFFSET(i9xx_plane), - (y << 16) | x); - } else if (INTEL_GEN(dev_priv) >= 4) { - intel_de_write_fw(dev_priv, DSPLINOFF(i9xx_plane), - linear_offset); - intel_de_write_fw(dev_priv, DSPTILEOFF(i9xx_plane), - (y << 16) | x); - } - - /* - * The control register self-arms if the plane was previously - * 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(i9xx_plane), dspcntr); - if (INTEL_GEN(dev_priv) >= 4) - intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), - intel_plane_ggtt_offset(plane_state) + dspaddr_offset); - else - intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), - intel_plane_ggtt_offset(plane_state) + dspaddr_offset); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); -} - -static void i9xx_disable_plane(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state) -{ - struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; - unsigned long irqflags; - u32 dspcntr; - - /* - * DSPCNTR pipe gamma enable on g4x+ and pipe csc - * enable on ilk+ affect the pipe bottom color as - * well, so we must configure them even if the plane - * is disabled. - * - * On pre-g4x there is no way to gamma correct the - * pipe bottom color but we'll keep on doing this - * anyway so that the crtc state readout works correctly. - */ - dspcntr = i9xx_plane_ctl_crtc(crtc_state); - - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - - intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr); - if (INTEL_GEN(dev_priv) >= 4) - intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), 0); - else - intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), 0); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); -} - -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); - enum intel_display_power_domain power_domain; - enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; - intel_wakeref_t wakeref; - bool ret; - u32 val; - - /* - * Not 100% correct for planes that can move between pipes, - * but that's only the case for gen2-4 which don't have any - * display power wells. - */ - power_domain = POWER_DOMAIN_PIPE(plane->pipe); - wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain); - if (!wakeref) - return false; - - val = intel_de_read(dev_priv, DSPCNTR(i9xx_plane)); - - ret = val & DISPLAY_PLANE_ENABLE; - - if (INTEL_GEN(dev_priv) >= 5) - *pipe = plane->pipe; - else - *pipe = (val & DISPPLANE_SEL_PIPE_MASK) >> - DISPPLANE_SEL_PIPE_SHIFT; - - intel_display_power_put(dev_priv, power_domain, wakeref); - - return ret; -} - static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id) { struct drm_device *dev = intel_crtc->base.dev; @@ -11908,33 +11446,6 @@ static void ilk_pch_clock_get(struct intel_crtc *crtc, &pipe_config->fdi_m_n); } -static void intel_crtc_state_reset(struct intel_crtc_state *crtc_state, - struct intel_crtc *crtc) -{ - memset(crtc_state, 0, sizeof(*crtc_state)); - - __drm_atomic_helper_crtc_state_reset(&crtc_state->uapi, &crtc->base); - - crtc_state->cpu_transcoder = INVALID_TRANSCODER; - crtc_state->master_transcoder = INVALID_TRANSCODER; - crtc_state->hsw_workaround_pipe = INVALID_PIPE; - crtc_state->output_format = INTEL_OUTPUT_FORMAT_INVALID; - crtc_state->scaler_state.scaler_id = -1; - crtc_state->mst_master_transcoder = INVALID_TRANSCODER; -} - -static struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc) -{ - struct intel_crtc_state *crtc_state; - - crtc_state = kmalloc(sizeof(*crtc_state), GFP_KERNEL); - - if (crtc_state) - intel_crtc_state_reset(crtc_state, crtc); - - return crtc_state; -} - /* Returns the currently programmed mode of the given encoder. */ struct drm_display_mode * intel_encoder_current_mode(struct intel_encoder *encoder) @@ -11975,14 +11486,6 @@ intel_encoder_current_mode(struct intel_encoder *encoder) return mode; } -static void intel_crtc_destroy(struct drm_crtc *crtc) -{ - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - - drm_crtc_cleanup(crtc); - kfree(intel_crtc); -} - /** * intel_wm_need_update - Check whether watermarks need updating * @cur: current plane state @@ -15186,17 +14689,6 @@ static int intel_atomic_prepare_commit(struct intel_atomic_state *state) return 0; } -u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc) -{ - struct drm_device *dev = crtc->base.dev; - struct drm_vblank_crtc *vblank = &dev->vblank[drm_crtc_index(&crtc->base)]; - - if (!vblank->max_vblank_count) - return (u32)drm_crtc_accurate_vblank_count(&crtc->base); - - return crtc->base.funcs->get_vblank_counter(&crtc->base); -} - void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state) { @@ -16249,336 +15741,6 @@ void intel_plane_destroy(struct drm_plane *plane) kfree(to_intel_plane(plane)); } -static bool i8xx_plane_format_mod_supported(struct drm_plane *_plane, - u32 format, u64 modifier) -{ - switch (modifier) { - case DRM_FORMAT_MOD_LINEAR: - case I915_FORMAT_MOD_X_TILED: - break; - default: - return false; - } - - switch (format) { - case DRM_FORMAT_C8: - case DRM_FORMAT_RGB565: - case DRM_FORMAT_XRGB1555: - case DRM_FORMAT_XRGB8888: - return modifier == DRM_FORMAT_MOD_LINEAR || - modifier == I915_FORMAT_MOD_X_TILED; - default: - return false; - } -} - -static bool i965_plane_format_mod_supported(struct drm_plane *_plane, - u32 format, u64 modifier) -{ - switch (modifier) { - case DRM_FORMAT_MOD_LINEAR: - case I915_FORMAT_MOD_X_TILED: - break; - default: - return false; - } - - switch (format) { - case DRM_FORMAT_C8: - case DRM_FORMAT_RGB565: - case DRM_FORMAT_XRGB8888: - case DRM_FORMAT_XBGR8888: - case DRM_FORMAT_ARGB8888: - case DRM_FORMAT_ABGR8888: - case DRM_FORMAT_XRGB2101010: - case DRM_FORMAT_XBGR2101010: - case DRM_FORMAT_ARGB2101010: - case DRM_FORMAT_ABGR2101010: - case DRM_FORMAT_XBGR16161616F: - return modifier == DRM_FORMAT_MOD_LINEAR || - modifier == I915_FORMAT_MOD_X_TILED; - default: - return false; - } -} - -static const struct drm_plane_funcs i965_plane_funcs = { - .update_plane = drm_atomic_helper_update_plane, - .disable_plane = drm_atomic_helper_disable_plane, - .destroy = intel_plane_destroy, - .atomic_duplicate_state = intel_plane_duplicate_state, - .atomic_destroy_state = intel_plane_destroy_state, - .format_mod_supported = i965_plane_format_mod_supported, -}; - -static const struct drm_plane_funcs i8xx_plane_funcs = { - .update_plane = drm_atomic_helper_update_plane, - .disable_plane = drm_atomic_helper_disable_plane, - .destroy = intel_plane_destroy, - .atomic_duplicate_state = intel_plane_duplicate_state, - .atomic_destroy_state = intel_plane_destroy_state, - .format_mod_supported = i8xx_plane_format_mod_supported, -}; - -static bool i9xx_plane_has_fbc(struct drm_i915_private *dev_priv, - enum i9xx_plane_id i9xx_plane) -{ - if (!HAS_FBC(dev_priv)) - return false; - - if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) - return i9xx_plane == PLANE_A; /* tied to pipe A */ - else if (IS_IVYBRIDGE(dev_priv)) - return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B || - i9xx_plane == PLANE_C; - else if (INTEL_GEN(dev_priv) >= 4) - return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B; - else - return i9xx_plane == PLANE_A; -} - -static struct intel_plane * -intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) -{ - struct intel_plane *plane; - const struct drm_plane_funcs *plane_funcs; - unsigned int supported_rotations; - const u32 *formats; - int num_formats; - int ret, zpos; - - if (INTEL_GEN(dev_priv) >= 9) - return skl_universal_plane_create(dev_priv, pipe, - PLANE_PRIMARY); - - plane = intel_plane_alloc(); - if (IS_ERR(plane)) - return plane; - - plane->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) && INTEL_GEN(dev_priv) < 4 && - INTEL_NUM_PIPES(dev_priv) == 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); - - plane->has_fbc = i9xx_plane_has_fbc(dev_priv, plane->i9xx_plane); - if (plane->has_fbc) { - struct intel_fbc *fbc = &dev_priv->fbc; - - fbc->possible_framebuffer_bits |= plane->frontbuffer_bit; - } - - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { - formats = vlv_primary_formats; - num_formats = ARRAY_SIZE(vlv_primary_formats); - } else if (INTEL_GEN(dev_priv) >= 4) { - /* - * WaFP16GammaEnabling:ivb - * "Workaround : When using the 64-bit format, the plane - * output on each color channel has one quarter amplitude. - * It can be brought up to full amplitude by using pipe - * gamma correction or pipe color space conversion to - * multiply the plane output by four." - * - * There is no dedicated plane gamma for the primary plane, - * and using the pipe gamma/csc could conflict with other - * 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)) { - formats = ivb_primary_formats; - num_formats = ARRAY_SIZE(ivb_primary_formats); - } else { - formats = i965_primary_formats; - num_formats = ARRAY_SIZE(i965_primary_formats); - } - } else { - formats = i8xx_primary_formats; - num_formats = ARRAY_SIZE(i8xx_primary_formats); - } - - if (INTEL_GEN(dev_priv) >= 4) - plane_funcs = &i965_plane_funcs; - else - plane_funcs = &i8xx_plane_funcs; - - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) - plane->min_cdclk = vlv_plane_min_cdclk; - else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) - plane->min_cdclk = hsw_plane_min_cdclk; - else if (IS_IVYBRIDGE(dev_priv)) - plane->min_cdclk = ivb_plane_min_cdclk; - else - plane->min_cdclk = i9xx_plane_min_cdclk; - - plane->max_stride = i9xx_plane_max_stride; - plane->update_plane = i9xx_update_plane; - plane->disable_plane = i9xx_disable_plane; - plane->get_hw_state = i9xx_plane_get_hw_state; - plane->check_plane = i9xx_plane_check; - - if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) - ret = drm_universal_plane_init(&dev_priv->drm, &plane->base, - 0, plane_funcs, - formats, num_formats, - i9xx_format_modifiers, - DRM_PLANE_TYPE_PRIMARY, - "primary %c", pipe_name(pipe)); - else - ret = drm_universal_plane_init(&dev_priv->drm, &plane->base, - 0, plane_funcs, - formats, num_formats, - i9xx_format_modifiers, - DRM_PLANE_TYPE_PRIMARY, - "plane %c", - plane_name(plane->i9xx_plane)); - if (ret) - goto fail; - - if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) { - supported_rotations = - DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 | - DRM_MODE_REFLECT_X; - } else if (INTEL_GEN(dev_priv) >= 4) { - supported_rotations = - DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180; - } else { - supported_rotations = DRM_MODE_ROTATE_0; - } - - if (INTEL_GEN(dev_priv) >= 4) - drm_plane_create_rotation_property(&plane->base, - DRM_MODE_ROTATE_0, - supported_rotations); - - zpos = 0; - drm_plane_create_zpos_immutable_property(&plane->base, zpos); - - drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs); - - return plane; - -fail: - intel_plane_free(plane); - - return ERR_PTR(ret); -} - -static int intel_crtc_late_register(struct drm_crtc *crtc) -{ - intel_crtc_debugfs_add(crtc); - return 0; -} - -#define INTEL_CRTC_FUNCS \ - .gamma_set = drm_atomic_helper_legacy_gamma_set, \ - .set_config = drm_atomic_helper_set_config, \ - .destroy = intel_crtc_destroy, \ - .page_flip = drm_atomic_helper_page_flip, \ - .atomic_duplicate_state = intel_crtc_duplicate_state, \ - .atomic_destroy_state = intel_crtc_destroy_state, \ - .set_crc_source = intel_crtc_set_crc_source, \ - .verify_crc_source = intel_crtc_verify_crc_source, \ - .get_crc_sources = intel_crtc_get_crc_sources, \ - .late_register = intel_crtc_late_register - -static const struct drm_crtc_funcs bdw_crtc_funcs = { - INTEL_CRTC_FUNCS, - - .get_vblank_counter = g4x_get_vblank_counter, - .enable_vblank = bdw_enable_vblank, - .disable_vblank = bdw_disable_vblank, - .get_vblank_timestamp = intel_crtc_get_vblank_timestamp, -}; - -static const struct drm_crtc_funcs ilk_crtc_funcs = { - INTEL_CRTC_FUNCS, - - .get_vblank_counter = g4x_get_vblank_counter, - .enable_vblank = ilk_enable_vblank, - .disable_vblank = ilk_disable_vblank, - .get_vblank_timestamp = intel_crtc_get_vblank_timestamp, -}; - -static const struct drm_crtc_funcs g4x_crtc_funcs = { - INTEL_CRTC_FUNCS, - - .get_vblank_counter = g4x_get_vblank_counter, - .enable_vblank = i965_enable_vblank, - .disable_vblank = i965_disable_vblank, - .get_vblank_timestamp = intel_crtc_get_vblank_timestamp, -}; - -static const struct drm_crtc_funcs i965_crtc_funcs = { - INTEL_CRTC_FUNCS, - - .get_vblank_counter = i915_get_vblank_counter, - .enable_vblank = i965_enable_vblank, - .disable_vblank = i965_disable_vblank, - .get_vblank_timestamp = intel_crtc_get_vblank_timestamp, -}; - -static const struct drm_crtc_funcs i915gm_crtc_funcs = { - INTEL_CRTC_FUNCS, - - .get_vblank_counter = i915_get_vblank_counter, - .enable_vblank = i915gm_enable_vblank, - .disable_vblank = i915gm_disable_vblank, - .get_vblank_timestamp = intel_crtc_get_vblank_timestamp, -}; - -static const struct drm_crtc_funcs i915_crtc_funcs = { - INTEL_CRTC_FUNCS, - - .get_vblank_counter = i915_get_vblank_counter, - .enable_vblank = i8xx_enable_vblank, - .disable_vblank = i8xx_disable_vblank, - .get_vblank_timestamp = intel_crtc_get_vblank_timestamp, -}; - -static const struct drm_crtc_funcs i8xx_crtc_funcs = { - INTEL_CRTC_FUNCS, - - /* no hw vblank counter */ - .enable_vblank = i8xx_enable_vblank, - .disable_vblank = i8xx_disable_vblank, - .get_vblank_timestamp = intel_crtc_get_vblank_timestamp, -}; - -static struct intel_crtc *intel_crtc_alloc(void) -{ - struct intel_crtc_state *crtc_state; - struct intel_crtc *crtc; - - crtc = kzalloc(sizeof(*crtc), GFP_KERNEL); - if (!crtc) - return ERR_PTR(-ENOMEM); - - crtc_state = intel_crtc_state_alloc(crtc); - if (!crtc_state) { - kfree(crtc); - return ERR_PTR(-ENOMEM); - } - - crtc->base.state = &crtc_state->uapi; - crtc->config = crtc_state; - - return crtc; -} - -static void intel_crtc_free(struct intel_crtc *crtc) -{ - intel_crtc_destroy_state(&crtc->base, crtc->base.state); - kfree(crtc); -} - static void intel_plane_possible_crtcs_init(struct drm_i915_private *dev_priv) { struct intel_plane *plane; @@ -16591,100 +15753,6 @@ static void intel_plane_possible_crtcs_init(struct drm_i915_private *dev_priv) } } -static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe) -{ - struct intel_plane *primary, *cursor; - const struct drm_crtc_funcs *funcs; - struct intel_crtc *crtc; - int sprite, ret; - - crtc = intel_crtc_alloc(); - if (IS_ERR(crtc)) - return PTR_ERR(crtc); - - crtc->pipe = pipe; - crtc->num_scalers = RUNTIME_INFO(dev_priv)->num_scalers[pipe]; - - primary = intel_primary_plane_create(dev_priv, pipe); - if (IS_ERR(primary)) { - ret = PTR_ERR(primary); - goto fail; - } - crtc->plane_ids_mask |= BIT(primary->id); - - for_each_sprite(dev_priv, pipe, sprite) { - struct intel_plane *plane; - - plane = intel_sprite_plane_create(dev_priv, pipe, sprite); - if (IS_ERR(plane)) { - ret = PTR_ERR(plane); - goto fail; - } - crtc->plane_ids_mask |= BIT(plane->id); - } - - cursor = intel_cursor_plane_create(dev_priv, pipe); - if (IS_ERR(cursor)) { - ret = PTR_ERR(cursor); - goto fail; - } - crtc->plane_ids_mask |= BIT(cursor->id); - - if (HAS_GMCH(dev_priv)) { - if (IS_CHERRYVIEW(dev_priv) || - IS_VALLEYVIEW(dev_priv) || IS_G4X(dev_priv)) - funcs = &g4x_crtc_funcs; - else if (IS_GEN(dev_priv, 4)) - funcs = &i965_crtc_funcs; - else if (IS_I945GM(dev_priv) || IS_I915GM(dev_priv)) - funcs = &i915gm_crtc_funcs; - else if (IS_GEN(dev_priv, 3)) - funcs = &i915_crtc_funcs; - else - funcs = &i8xx_crtc_funcs; - } else { - if (INTEL_GEN(dev_priv) >= 8) - funcs = &bdw_crtc_funcs; - else - funcs = &ilk_crtc_funcs; - } - - ret = drm_crtc_init_with_planes(&dev_priv->drm, &crtc->base, - &primary->base, &cursor->base, - funcs, "pipe %c", pipe_name(pipe)); - if (ret) - goto fail; - - BUG_ON(pipe >= ARRAY_SIZE(dev_priv->pipe_to_crtc_mapping) || - dev_priv->pipe_to_crtc_mapping[pipe] != NULL); - dev_priv->pipe_to_crtc_mapping[pipe] = crtc; - - if (INTEL_GEN(dev_priv) < 9) { - enum i9xx_plane_id i9xx_plane = primary->i9xx_plane; - - BUG_ON(i9xx_plane >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) || - dev_priv->plane_to_crtc_mapping[i9xx_plane] != NULL); - dev_priv->plane_to_crtc_mapping[i9xx_plane] = crtc; - } - - if (INTEL_GEN(dev_priv) >= 10) - drm_crtc_create_scaling_filter_property(&crtc->base, - BIT(DRM_SCALING_FILTER_DEFAULT) | - BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR)); - - intel_color_init(crtc); - - intel_crtc_crc_init(crtc); - - drm_WARN_ON(&dev_priv->drm, drm_crtc_index(&crtc->base) != crtc->pipe); - - return 0; - -fail: - intel_crtc_free(crtc); - - return ret; -} int intel_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data, struct drm_file *file) diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index f0a5bf69656f..0eba91d18e96 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -659,6 +659,13 @@ struct intel_plane * intel_cursor_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe); +/* crtc */ +u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state); +int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe); +struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc); +void intel_crtc_state_reset(struct intel_crtc_state *crtc_state, + struct intel_crtc *crtc); + /* modesetting */ void intel_modeset_init_hw(struct drm_i915_private *i915); int intel_modeset_init_noirq(struct drm_i915_private *i915);