Message ID | 20201211072922.19101-6-airlied@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [01/11] drm/i915/display: move needs_modeset to an inline in header | expand |
On Fri, 11 Dec 2020, Dave Airlie <airlied@gmail.com> wrote: > From: Dave Airlie <airlied@redhat.com> > > There may be more crtc code that can be pulled out, but this > is a good start. > > RFC: maybe call the new file something different I checked this is just code movement. I did clean up intel_crtc.h locally a bit though. (I'll probably re-send the series with a few fixes to pass CI.) I'm not averse to renaming the file later if needed, I'm more concerned about choosing a meaningful bunch of functions to take out and put in the new file. Ville, I saw you had some comments about this - is this making sensible progress or making further refactoring harder? I'm honestly beginning to think we've had too many stalled attempts at cleaning up the file (including at least three patch series from yours truly) that I'm ready to just chop up the file, and clean it up more later as needed. BR, Jani. > > Signed-off-by: Dave Airlie <airlied@redhat.com> > --- > drivers/gpu/drm/i915/Makefile | 1 + > drivers/gpu/drm/i915/display/intel_crtc.c | 953 +++++++++++++++++++ > drivers/gpu/drm/i915/display/intel_crtc.h | 20 + > drivers/gpu/drm/i915/display/intel_display.c | 934 +----------------- > 4 files changed, 975 insertions(+), 933 deletions(-) > create mode 100644 drivers/gpu/drm/i915/display/intel_crtc.c > create mode 100644 drivers/gpu/drm/i915/display/intel_crtc.h > > 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..d26beb8ad9ed > --- /dev/null > +++ b/drivers/gpu/drm/i915/display/intel_crtc.c > @@ -0,0 +1,953 @@ > +// 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_crtc.h" > +#include "intel_cursor.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_crtc.h b/drivers/gpu/drm/i915/display/intel_crtc.h > new file mode 100644 > index 000000000000..da28af75ae22 > --- /dev/null > +++ b/drivers/gpu/drm/i915/display/intel_crtc.h > @@ -0,0 +1,20 @@ > +/* SPDX-License-Identifier: MIT */ > +/* > + * Copyright © 2020 Intel Corporation > + */ > + > +#ifndef _INTEL_CRTC_H_ > +#define _INTEL_CRTC_H_ > + > +#include "intel_display.h" > + > +struct intel_crtc_state; > + > +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); > + > + > +#endif > diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c > index 28855844f8de..5dfec950c144 100644 > --- a/drivers/gpu/drm/i915/display/intel_display.c > +++ b/drivers/gpu/drm/i915/display/intel_display.c > @@ -68,8 +68,8 @@ > #include "intel_bw.h" > #include "intel_cdclk.h" > #include "intel_color.h" > +#include "intel_crtc.h" > #include "intel_csr.h" > -#include "intel_cursor.h" > #include "intel_display_types.h" > #include "intel_dp_link_training.h" > #include "intel_fbc.h" > @@ -88,56 +88,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, > @@ -163,7 +113,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 { > @@ -1302,12 +1251,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) > { > @@ -1792,55 +1735,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); > @@ -4047,171 +3941,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 = > @@ -4272,197 +4001,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; > @@ -11909,33 +11447,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) > @@ -11976,14 +11487,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 > @@ -15187,17 +14690,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) > { > @@ -16250,336 +15742,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; > @@ -16592,100 +15754,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)
On Wed, Dec 16, 2020 at 12:03:37PM +0200, Jani Nikula wrote: > On Fri, 11 Dec 2020, Dave Airlie <airlied@gmail.com> wrote: > > From: Dave Airlie <airlied@redhat.com> > > > > There may be more crtc code that can be pulled out, but this > > is a good start. > > > > RFC: maybe call the new file something different > > I checked this is just code movement. I did clean up intel_crtc.h > locally a bit though. (I'll probably re-send the series with a few fixes > to pass CI.) > > I'm not averse to renaming the file later if needed, I'm more concerned > about choosing a meaningful bunch of functions to take out and put in > the new file. > > Ville, I saw you had some comments about this - is this making sensible > progress or making further refactoring harder? Just means we have to move 90% of the proposed intel_crtc.c into i9xx_plane.c again. So the plane bits here are just pointless churn IMO.
On Wed, 16 Dec 2020, Ville Syrjälä <ville.syrjala@intel.com> wrote: > On Wed, Dec 16, 2020 at 12:03:37PM +0200, Jani Nikula wrote: >> On Fri, 11 Dec 2020, Dave Airlie <airlied@gmail.com> wrote: >> > From: Dave Airlie <airlied@redhat.com> >> > >> > There may be more crtc code that can be pulled out, but this >> > is a good start. >> > >> > RFC: maybe call the new file something different >> >> I checked this is just code movement. I did clean up intel_crtc.h >> locally a bit though. (I'll probably re-send the series with a few fixes >> to pass CI.) >> >> I'm not averse to renaming the file later if needed, I'm more concerned >> about choosing a meaningful bunch of functions to take out and put in >> the new file. >> >> Ville, I saw you had some comments about this - is this making sensible >> progress or making further refactoring harder? > > Just means we have to move 90% of the proposed intel_crtc.c > into i9xx_plane.c again. So the plane bits here are just > pointless churn IMO. Fair enough. I just don't want to stall on this again like we've stalled every time there's been proposals to clean up intel_display.c. And it's always about some things that could be moved to a different file or grouped differently or something. I'm pretty close to a point where I'll take *anything* to chop up the file, and then we'll have better clarity with smaller files when the dust settles. BR, Jani.
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..d26beb8ad9ed --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_crtc.c @@ -0,0 +1,953 @@ +// 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_crtc.h" +#include "intel_cursor.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_crtc.h b/drivers/gpu/drm/i915/display/intel_crtc.h new file mode 100644 index 000000000000..da28af75ae22 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_crtc.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2020 Intel Corporation + */ + +#ifndef _INTEL_CRTC_H_ +#define _INTEL_CRTC_H_ + +#include "intel_display.h" + +struct intel_crtc_state; + +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); + + +#endif diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 28855844f8de..5dfec950c144 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -68,8 +68,8 @@ #include "intel_bw.h" #include "intel_cdclk.h" #include "intel_color.h" +#include "intel_crtc.h" #include "intel_csr.h" -#include "intel_cursor.h" #include "intel_display_types.h" #include "intel_dp_link_training.h" #include "intel_fbc.h" @@ -88,56 +88,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, @@ -163,7 +113,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 { @@ -1302,12 +1251,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) { @@ -1792,55 +1735,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); @@ -4047,171 +3941,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 = @@ -4272,197 +4001,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; @@ -11909,33 +11447,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) @@ -11976,14 +11487,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 @@ -15187,17 +14690,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) { @@ -16250,336 +15742,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; @@ -16592,100 +15754,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)