diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_sprite.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_sprite.c | 260 |
1 files changed, 230 insertions, 30 deletions
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index b56a1a9ad01d..2913e89280d7 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -29,17 +29,36 @@ * registers; newer ones are much simpler and we can use the new DRM plane * support. */ + +#include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_color_mgmt.h> #include <drm/drm_crtc.h> #include <drm/drm_fourcc.h> -#include <drm/drm_rect.h> -#include <drm/drm_atomic.h> #include <drm/drm_plane_helper.h> -#include "intel_drv.h" -#include "intel_frontbuffer.h" +#include <drm/drm_rect.h> #include <drm/i915_drm.h> + #include "i915_drv.h" -#include <drm/drm_color_mgmt.h> +#include "intel_atomic_plane.h" +#include "intel_drv.h" +#include "intel_frontbuffer.h" +#include "intel_pm.h" +#include "intel_psr.h" +#include "intel_sprite.h" + +bool is_planar_yuv_format(u32 pixelformat) +{ + switch (pixelformat) { + case DRM_FORMAT_NV12: + case DRM_FORMAT_P010: + case DRM_FORMAT_P012: + case DRM_FORMAT_P016: + return true; + default: + return false; + } +} int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, int usecs) @@ -256,7 +275,8 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state) { const struct drm_framebuffer *fb = plane_state->base.fb; struct drm_rect *src = &plane_state->base.src; - u32 src_x, src_y, src_w, src_h; + u32 src_x, src_y, src_w, src_h, hsub, vsub; + bool rotated = drm_rotation_90_or_270(plane_state->base.rotation); /* * Hardware doesn't handle subpixel coordinates. @@ -274,18 +294,26 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state) src->y1 = src_y << 16; src->y2 = (src_y + src_h) << 16; - if (fb->format->is_yuv && - (src_x & 1 || src_w & 1)) { - DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of 2 for YUV planes\n", - src_x, src_w); + if (!fb->format->is_yuv) + return 0; + + /* YUV specific checks */ + if (!rotated) { + hsub = fb->format->hsub; + vsub = fb->format->vsub; + } else { + hsub = vsub = max(fb->format->hsub, fb->format->vsub); + } + + if (src_x % hsub || src_w % hsub) { + DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of %u for %sYUV planes\n", + src_x, src_w, hsub, rotated ? "rotated " : ""); return -EINVAL; } - if (fb->format->is_yuv && - fb->format->num_planes > 1 && - (src_y & 1 || src_h & 1)) { - DRM_DEBUG_KMS("src y/h (%u, %u) must be a multiple of 2 for planar YUV planes\n", - src_y, src_h); + if (src_y % vsub || src_h % vsub) { + DRM_DEBUG_KMS("src y/h (%u, %u) must be a multiple of %u for %sYUV planes\n", + src_y, src_h, vsub, rotated ? "rotated " : ""); return -EINVAL; } @@ -335,8 +363,8 @@ skl_program_scaler(struct intel_plane *plane, 0, INT_MAX); /* TODO: handle sub-pixel coordinates */ - if (plane_state->base.fb->format->format == DRM_FORMAT_NV12 && - !icl_is_hdr_plane(plane)) { + if (is_planar_yuv_format(plane_state->base.fb->format->format) && + !icl_is_hdr_plane(dev_priv, plane->id)) { y_hphase = skl_scaler_calc_phase(1, hscale, false); y_vphase = skl_scaler_calc_phase(1, vscale, false); @@ -518,7 +546,7 @@ skl_program_plane(struct intel_plane *plane, I915_WRITE_FW(PLANE_AUX_DIST(pipe, plane_id), (plane_state->color_plane[1].offset - surf_addr) | aux_stride); - if (icl_is_hdr_plane(plane)) { + if (icl_is_hdr_plane(dev_priv, plane_id)) { u32 cus_ctl = 0; if (linked) { @@ -542,7 +570,7 @@ skl_program_plane(struct intel_plane *plane, if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) I915_WRITE_FW(PLANE_COLOR_CTL(pipe, plane_id), plane_color_ctl); - if (fb->format->is_yuv && icl_is_hdr_plane(plane)) + if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id)) icl_program_input_csc(plane, crtc_state, plane_state); skl_write_plane_wm(plane, crtc_state); @@ -609,6 +637,9 @@ skl_disable_plane(struct intel_plane *plane, spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + if (icl_is_hdr_plane(dev_priv, plane_id)) + I915_WRITE_FW(PLANE_CUS_CTL(pipe, plane_id), 0); + skl_write_plane_wm(plane, crtc_state); I915_WRITE_FW(PLANE_CTL(pipe, plane_id), 0); @@ -741,7 +772,12 @@ vlv_update_clrc(const struct intel_plane_state *plane_state) static u32 vlv_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state) { - return SP_GAMMA_ENABLE; + u32 sprctl = 0; + + if (crtc_state->gamma_enable) + sprctl |= SP_GAMMA_ENABLE; + + return sprctl; } static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state, @@ -916,12 +952,12 @@ vlv_plane_get_hw_state(struct intel_plane *plane, static u32 ivb_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); u32 sprctl = 0; - sprctl |= SPRITE_GAMMA_ENABLE; + if (crtc_state->gamma_enable) + sprctl |= SPRITE_GAMMA_ENABLE; - if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) + if (crtc_state->csc_enable) sprctl |= SPRITE_PIPE_CSC_ENABLE; return sprctl; @@ -1107,7 +1143,15 @@ g4x_sprite_max_stride(struct intel_plane *plane, static u32 g4x_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state) { - return DVS_GAMMA_ENABLE; + u32 dvscntr = 0; + + if (crtc_state->gamma_enable) + dvscntr |= DVS_GAMMA_ENABLE; + + if (crtc_state->csc_enable) + dvscntr |= DVS_PIPE_CSC_ENABLE; + + return dvscntr; } static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state, @@ -1482,8 +1526,6 @@ static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state, /* * 90/270 is not allowed with RGB64 16:16:16:16 and * Indexed 8-bit. RGB 16-bit 5:6:5 is allowed gen11 onwards. - * TBD: Add RGB64 case once its added in supported format - * list. */ switch (fb->format->format) { case DRM_FORMAT_RGB565: @@ -1491,6 +1533,15 @@ static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state, break; /* fall through */ case DRM_FORMAT_C8: + case DRM_FORMAT_XRGB16161616F: + case DRM_FORMAT_XBGR16161616F: + case DRM_FORMAT_ARGB16161616F: + case DRM_FORMAT_ABGR16161616F: + case DRM_FORMAT_Y210: + case DRM_FORMAT_Y212: + case DRM_FORMAT_Y216: + case DRM_FORMAT_XVYU12_16161616: + case DRM_FORMAT_XVYU16161616: DRM_DEBUG_KMS("Unsupported pixel format %s for 90/270!\n", drm_get_format_name(fb->format->format, &format_name)); @@ -1551,10 +1602,10 @@ static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_s int src_w = drm_rect_width(&plane_state->base.src) >> 16; /* Display WA #1106 */ - if (fb->format->format == DRM_FORMAT_NV12 && src_w & 3 && + if (is_planar_yuv_format(fb->format->format) && src_w & 3 && (rotation == DRM_MODE_ROTATE_270 || rotation == (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90))) { - DRM_DEBUG_KMS("src width must be multiple of 4 for rotated NV12\n"); + DRM_DEBUG_KMS("src width must be multiple of 4 for rotated planar YUV\n"); return -EINVAL; } @@ -1790,6 +1841,52 @@ static const u32 skl_plane_formats[] = { DRM_FORMAT_VYUY, }; +static const u32 icl_plane_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_YUYV, + DRM_FORMAT_YVYU, + DRM_FORMAT_UYVY, + DRM_FORMAT_VYUY, + DRM_FORMAT_Y210, + DRM_FORMAT_Y212, + DRM_FORMAT_Y216, + DRM_FORMAT_XVYU2101010, + DRM_FORMAT_XVYU12_16161616, + DRM_FORMAT_XVYU16161616, +}; + +static const u32 icl_hdr_plane_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_XRGB16161616F, + DRM_FORMAT_XBGR16161616F, + DRM_FORMAT_ARGB16161616F, + DRM_FORMAT_ABGR16161616F, + DRM_FORMAT_YUYV, + DRM_FORMAT_YVYU, + DRM_FORMAT_UYVY, + DRM_FORMAT_VYUY, + DRM_FORMAT_Y210, + DRM_FORMAT_Y212, + DRM_FORMAT_Y216, + DRM_FORMAT_XVYU2101010, + DRM_FORMAT_XVYU12_16161616, + DRM_FORMAT_XVYU16161616, +}; + static const u32 skl_planar_formats[] = { DRM_FORMAT_C8, DRM_FORMAT_RGB565, @@ -1806,6 +1903,79 @@ static const u32 skl_planar_formats[] = { DRM_FORMAT_NV12, }; +static const u32 glk_planar_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_YUYV, + DRM_FORMAT_YVYU, + DRM_FORMAT_UYVY, + DRM_FORMAT_VYUY, + DRM_FORMAT_NV12, + DRM_FORMAT_P010, + DRM_FORMAT_P012, + DRM_FORMAT_P016, +}; + +static const u32 icl_planar_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_YUYV, + DRM_FORMAT_YVYU, + DRM_FORMAT_UYVY, + DRM_FORMAT_VYUY, + DRM_FORMAT_NV12, + DRM_FORMAT_P010, + DRM_FORMAT_P012, + DRM_FORMAT_P016, + DRM_FORMAT_Y210, + DRM_FORMAT_Y212, + DRM_FORMAT_Y216, + DRM_FORMAT_XVYU2101010, + DRM_FORMAT_XVYU12_16161616, + DRM_FORMAT_XVYU16161616, +}; + +static const u32 icl_hdr_planar_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_XRGB16161616F, + DRM_FORMAT_XBGR16161616F, + DRM_FORMAT_ARGB16161616F, + DRM_FORMAT_ABGR16161616F, + DRM_FORMAT_YUYV, + DRM_FORMAT_YVYU, + DRM_FORMAT_UYVY, + DRM_FORMAT_VYUY, + DRM_FORMAT_NV12, + DRM_FORMAT_P010, + DRM_FORMAT_P012, + DRM_FORMAT_P016, + DRM_FORMAT_Y210, + DRM_FORMAT_Y212, + DRM_FORMAT_Y216, + DRM_FORMAT_XVYU2101010, + DRM_FORMAT_XVYU12_16161616, + DRM_FORMAT_XVYU16161616, +}; + static const u64 skl_plane_format_modifiers_noccs[] = { I915_FORMAT_MOD_Yf_TILED, I915_FORMAT_MOD_Y_TILED, @@ -1945,10 +2115,23 @@ static bool skl_plane_format_mod_supported(struct drm_plane *_plane, case DRM_FORMAT_UYVY: case DRM_FORMAT_VYUY: case DRM_FORMAT_NV12: + case DRM_FORMAT_P010: + case DRM_FORMAT_P012: + case DRM_FORMAT_P016: + case DRM_FORMAT_XVYU2101010: if (modifier == I915_FORMAT_MOD_Yf_TILED) return true; /* fall through */ case DRM_FORMAT_C8: + case DRM_FORMAT_XBGR16161616F: + case DRM_FORMAT_ABGR16161616F: + case DRM_FORMAT_XRGB16161616F: + case DRM_FORMAT_ARGB16161616F: + case DRM_FORMAT_Y210: + case DRM_FORMAT_Y212: + case DRM_FORMAT_Y216: + case DRM_FORMAT_XVYU12_16161616: + case DRM_FORMAT_XVYU16161616: if (modifier == DRM_FORMAT_MOD_LINEAR || modifier == I915_FORMAT_MOD_X_TILED || modifier == I915_FORMAT_MOD_Y_TILED) @@ -2085,8 +2268,25 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, plane->update_slave = icl_update_slave; if (skl_plane_has_planar(dev_priv, pipe, plane_id)) { - formats = skl_planar_formats; - num_formats = ARRAY_SIZE(skl_planar_formats); + if (icl_is_hdr_plane(dev_priv, plane_id)) { + formats = icl_hdr_planar_formats; + num_formats = ARRAY_SIZE(icl_hdr_planar_formats); + } else if (INTEL_GEN(dev_priv) >= 11) { + formats = icl_planar_formats; + num_formats = ARRAY_SIZE(icl_planar_formats); + } else if (INTEL_GEN(dev_priv) == 10 || IS_GEMINILAKE(dev_priv)) { + formats = glk_planar_formats; + num_formats = ARRAY_SIZE(glk_planar_formats); + } else { + formats = skl_planar_formats; + num_formats = ARRAY_SIZE(skl_planar_formats); + } + } else if (icl_is_hdr_plane(dev_priv, plane_id)) { + formats = icl_hdr_plane_formats; + num_formats = ARRAY_SIZE(icl_hdr_plane_formats); + } else if (INTEL_GEN(dev_priv) >= 11) { + formats = icl_plane_formats; + num_formats = ARRAY_SIZE(icl_plane_formats); } else { formats = skl_plane_formats; num_formats = ARRAY_SIZE(skl_plane_formats); |