[Intel-gfx] [PATCH v12 1/8] drm/i915: migrate skl planes code new file (v5)
Ville Syrjälä
ville.syrjala at linux.intel.com
Fri Feb 5 15:01:51 UTC 2021
On Fri, Feb 05, 2021 at 04:48:36PM +0200, Jani Nikula wrote:
> From: Dave Airlie <airlied at redhat.com>
>
> Rework the plane init calls to do the gen test one level higher.
>
> Rework some of the plane helpers so they can live in new file,
> there is still some scope to clean up the plane/fb interactions
> later.
>
> v2: drop atomic code back, rename file to Ville suggestions,
> add header file.
> v3: move scaler bits back
> v4: drop wrong new includes (Ville)
> v5: integrate the ccs gen12 changes
> v6: fix unrelated code movement (Ville)
>
> Signed-off-by: Dave Airlie <airlied at redhat.com>
> [Jani: fixed up sparse warnings.]
> Signed-off-by: Jani Nikula <jani.nikula at intel.com>
> Reported-by: kernel test robot <lkp at intel.com>
> Reported-by: Dan Carpenter <dan.carpenter at oracle.com>
Reviewed-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
> ---
> drivers/gpu/drm/i915/Makefile | 3 +-
> drivers/gpu/drm/i915/display/i9xx_plane.c | 4 -
> drivers/gpu/drm/i915/display/icl_dsi.c | 1 +
> drivers/gpu/drm/i915/display/intel_crtc.c | 13 +-
> drivers/gpu/drm/i915/display/intel_ddi.c | 1 +
> drivers/gpu/drm/i915/display/intel_display.c | 948 +------
> drivers/gpu/drm/i915/display/intel_display.h | 27 +-
> .../drm/i915/display/intel_display_types.h | 27 +
> drivers/gpu/drm/i915/display/intel_psr.c | 1 +
> drivers/gpu/drm/i915/display/intel_sprite.c | 1343 +---------
> drivers/gpu/drm/i915/display/intel_sprite.h | 6 +-
> .../drm/i915/display/skl_universal_plane.c | 2265 +++++++++++++++++
> .../drm/i915/display/skl_universal_plane.h | 33 +
> drivers/gpu/drm/i915/intel_pm.c | 1 +
> 14 files changed, 2380 insertions(+), 2293 deletions(-)
> create mode 100644 drivers/gpu/drm/i915/display/skl_universal_plane.c
> create mode 100644 drivers/gpu/drm/i915/display/skl_universal_plane.h
>
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index d571e87416dc..9388e09184fe 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -225,7 +225,8 @@ i915-y += \
> display/intel_sprite.o \
> display/intel_tc.o \
> display/intel_vga.o \
> - display/i9xx_plane.o
> + display/i9xx_plane.o \
> + display/skl_universal_plane.o
> i915-$(CONFIG_ACPI) += \
> display/intel_acpi.o \
> display/intel_opregion.o
> diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c
> index d30374df67f0..d116dee201aa 100644
> --- a/drivers/gpu/drm/i915/display/i9xx_plane.c
> +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c
> @@ -743,10 +743,6 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
> 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;
> diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c
> index 9d245a689323..9eeec6fadec7 100644
> --- a/drivers/gpu/drm/i915/display/icl_dsi.c
> +++ b/drivers/gpu/drm/i915/display/icl_dsi.c
> @@ -35,6 +35,7 @@
> #include "intel_dsi.h"
> #include "intel_panel.h"
> #include "intel_vdsc.h"
> +#include "skl_universal_plane.h"
>
> static int header_credits_available(struct drm_i915_private *dev_priv,
> enum transcoder dsi_trans)
> diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c
> index 57b0a3ebe908..eb478712c381 100644
> --- a/drivers/gpu/drm/i915/display/intel_crtc.c
> +++ b/drivers/gpu/drm/i915/display/intel_crtc.c
> @@ -20,6 +20,7 @@
> #include "intel_pipe_crc.h"
> #include "intel_sprite.h"
> #include "i9xx_plane.h"
> +#include "skl_universal_plane.h"
>
> static void assert_vblank_disabled(struct drm_crtc *crtc)
> {
> @@ -243,7 +244,11 @@ int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
> crtc->pipe = pipe;
> crtc->num_scalers = RUNTIME_INFO(dev_priv)->num_scalers[pipe];
>
> - primary = intel_primary_plane_create(dev_priv, pipe);
> + if (INTEL_GEN(dev_priv) >= 9)
> + primary = skl_universal_plane_create(dev_priv, pipe,
> + PLANE_PRIMARY);
> + else
> + primary = intel_primary_plane_create(dev_priv, pipe);
> if (IS_ERR(primary)) {
> ret = PTR_ERR(primary);
> goto fail;
> @@ -253,7 +258,11 @@ int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
> for_each_sprite(dev_priv, pipe, sprite) {
> struct intel_plane *plane;
>
> - plane = intel_sprite_plane_create(dev_priv, pipe, sprite);
> + if (INTEL_GEN(dev_priv) >= 9)
> + plane = skl_universal_plane_create(dev_priv, pipe,
> + PLANE_SPRITE0 + sprite);
> + else
> + plane = intel_sprite_plane_create(dev_priv, pipe, sprite);
> if (IS_ERR(plane)) {
> ret = PTR_ERR(plane);
> goto fail;
> diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
> index 28877a31adc0..f4746c1edabe 100644
> --- a/drivers/gpu/drm/i915/display/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/display/intel_ddi.c
> @@ -54,6 +54,7 @@
> #include "intel_tc.h"
> #include "intel_vdsc.h"
> #include "intel_vrr.h"
> +#include "skl_universal_plane.h"
>
> static const u8 index_to_dp_signal_levels[] = {
> [0] = DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0,
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 92c14f3f0abf..a259ca5433f7 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -94,6 +94,7 @@
> #include "intel_tc.h"
> #include "intel_vga.h"
> #include "i9xx_plane.h"
> +#include "skl_universal_plane.h"
>
> static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
> struct intel_crtc_state *pipe_config);
> @@ -116,7 +117,6 @@ static void vlv_prepare_pll(struct intel_crtc *crtc,
> const struct intel_crtc_state *pipe_config);
> static void chv_prepare_pll(struct intel_crtc *crtc,
> const struct intel_crtc_state *pipe_config);
> -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);
> @@ -1082,32 +1082,6 @@ static unsigned int intel_tile_size(const struct drm_i915_private *dev_priv)
> return IS_GEN(dev_priv, 2) ? 2048 : 4096;
> }
>
> -static bool is_ccs_plane(const struct drm_framebuffer *fb, int plane)
> -{
> - if (!is_ccs_modifier(fb->modifier))
> - return false;
> -
> - return plane >= fb->format->num_planes / 2;
> -}
> -
> -static bool is_gen12_ccs_modifier(u64 modifier)
> -{
> - return modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS ||
> - modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC ||
> - modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS;
> -}
> -
> -static bool is_gen12_ccs_plane(const struct drm_framebuffer *fb, int plane)
> -{
> - return is_gen12_ccs_modifier(fb->modifier) && is_ccs_plane(fb, plane);
> -}
> -
> -static bool is_gen12_ccs_cc_plane(const struct drm_framebuffer *fb, int plane)
> -{
> - return fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC &&
> - plane == 2;
> -}
> -
> static bool is_aux_plane(const struct drm_framebuffer *fb, int plane)
> {
> if (is_ccs_modifier(fb->modifier))
> @@ -1116,38 +1090,6 @@ static bool is_aux_plane(const struct drm_framebuffer *fb, int plane)
> return plane == 1;
> }
>
> -static int main_to_ccs_plane(const struct drm_framebuffer *fb, int main_plane)
> -{
> - drm_WARN_ON(fb->dev, !is_ccs_modifier(fb->modifier) ||
> - (main_plane && main_plane >= fb->format->num_planes / 2));
> -
> - return fb->format->num_planes / 2 + main_plane;
> -}
> -
> -static int ccs_to_main_plane(const struct drm_framebuffer *fb, int ccs_plane)
> -{
> - drm_WARN_ON(fb->dev, !is_ccs_modifier(fb->modifier) ||
> - ccs_plane < fb->format->num_planes / 2);
> -
> - if (is_gen12_ccs_cc_plane(fb, ccs_plane))
> - return 0;
> -
> - return ccs_plane - fb->format->num_planes / 2;
> -}
> -
> -int intel_main_to_aux_plane(const struct drm_framebuffer *fb, int main_plane)
> -{
> - struct drm_i915_private *i915 = to_i915(fb->dev);
> -
> - if (is_ccs_modifier(fb->modifier))
> - return main_to_ccs_plane(fb, main_plane);
> - else if (INTEL_GEN(i915) < 11 &&
> - intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
> - return 1;
> - else
> - return 0;
> -}
> -
> bool
> intel_format_info_is_yuv_semiplanar(const struct drm_format_info *info,
> u64 modifier)
> @@ -1163,7 +1105,7 @@ static bool is_semiplanar_uv_plane(const struct drm_framebuffer *fb,
> color_plane == 1;
> }
>
> -static unsigned int
> +unsigned int
> intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane)
> {
> struct drm_i915_private *dev_priv = to_i915(fb->dev);
> @@ -1217,7 +1159,7 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane)
> }
> }
>
> -static unsigned int
> +unsigned int
> intel_tile_height(const struct drm_framebuffer *fb, int color_plane)
> {
> if (is_gen12_ccs_plane(fb, color_plane))
> @@ -1322,8 +1264,8 @@ static bool has_async_flips(struct drm_i915_private *i915)
> return INTEL_GEN(i915) >= 5;
> }
>
> -static unsigned int intel_surf_alignment(const struct drm_framebuffer *fb,
> - int color_plane)
> +unsigned int intel_surf_alignment(const struct drm_framebuffer *fb,
> + int color_plane)
> {
> struct drm_i915_private *dev_priv = to_i915(fb->dev);
>
> @@ -1590,10 +1532,10 @@ static u32 intel_adjust_aligned_offset(int *x, int *y,
> * Adjust the tile offset by moving the difference into
> * the x/y offsets.
> */
> -static u32 intel_plane_adjust_aligned_offset(int *x, int *y,
> - const struct intel_plane_state *state,
> - int color_plane,
> - u32 old_offset, u32 new_offset)
> +u32 intel_plane_adjust_aligned_offset(int *x, int *y,
> + const struct intel_plane_state *state,
> + int color_plane,
> + u32 old_offset, u32 new_offset)
> {
> return intel_adjust_aligned_offset(x, y, state->hw.fb, color_plane,
> state->hw.rotation,
> @@ -1892,7 +1834,7 @@ bool is_ccs_modifier(u64 modifier)
>
> static int gen12_ccs_aux_stride(struct drm_framebuffer *fb, int ccs_plane)
> {
> - return DIV_ROUND_UP(fb->pitches[ccs_to_main_plane(fb, ccs_plane)],
> + return DIV_ROUND_UP(fb->pitches[skl_ccs_to_main_plane(fb, ccs_plane)],
> 512) * 64;
> }
>
> @@ -2050,7 +1992,7 @@ static bool intel_plane_needs_remap(const struct intel_plane_state *plane_state)
> return stride > max_stride;
> }
>
> -static void
> +void
> intel_fb_plane_get_subsampling(int *hsub, int *vsub,
> const struct drm_framebuffer *fb,
> int color_plane)
> @@ -2075,7 +2017,7 @@ intel_fb_plane_get_subsampling(int *hsub, int *vsub,
> return;
> }
>
> - main_plane = ccs_to_main_plane(fb, color_plane);
> + main_plane = skl_ccs_to_main_plane(fb, color_plane);
> *hsub = drm_format_info_block_width(fb->format, color_plane) /
> drm_format_info_block_width(fb->format, main_plane);
>
> @@ -2115,7 +2057,7 @@ intel_fb_check_ccs_xy(struct drm_framebuffer *fb, int ccs_plane, int x, int y)
> ccs_x = (x * hsub) % tile_width;
> ccs_y = (y * vsub) % tile_height;
>
> - main_plane = ccs_to_main_plane(fb, ccs_plane);
> + main_plane = skl_ccs_to_main_plane(fb, ccs_plane);
> main_x = intel_fb->normal[main_plane].x % tile_width;
> main_y = intel_fb->normal[main_plane].y % tile_height;
>
> @@ -2141,7 +2083,7 @@ static void
> intel_fb_plane_dims(int *w, int *h, struct drm_framebuffer *fb, int color_plane)
> {
> int main_plane = is_ccs_plane(fb, color_plane) ?
> - ccs_to_main_plane(fb, color_plane) : 0;
> + skl_ccs_to_main_plane(fb, color_plane) : 0;
> int main_hsub, main_vsub;
> int hsub, vsub;
>
> @@ -2528,73 +2470,6 @@ static int i9xx_format_to_fourcc(int format)
> }
> }
>
> -int skl_format_to_fourcc(int format, bool rgb_order, bool alpha)
> -{
> - switch (format) {
> - case PLANE_CTL_FORMAT_RGB_565:
> - return DRM_FORMAT_RGB565;
> - case PLANE_CTL_FORMAT_NV12:
> - return DRM_FORMAT_NV12;
> - case PLANE_CTL_FORMAT_XYUV:
> - return DRM_FORMAT_XYUV8888;
> - case PLANE_CTL_FORMAT_P010:
> - return DRM_FORMAT_P010;
> - case PLANE_CTL_FORMAT_P012:
> - return DRM_FORMAT_P012;
> - case PLANE_CTL_FORMAT_P016:
> - return DRM_FORMAT_P016;
> - case PLANE_CTL_FORMAT_Y210:
> - return DRM_FORMAT_Y210;
> - case PLANE_CTL_FORMAT_Y212:
> - return DRM_FORMAT_Y212;
> - case PLANE_CTL_FORMAT_Y216:
> - return DRM_FORMAT_Y216;
> - case PLANE_CTL_FORMAT_Y410:
> - return DRM_FORMAT_XVYU2101010;
> - case PLANE_CTL_FORMAT_Y412:
> - return DRM_FORMAT_XVYU12_16161616;
> - case PLANE_CTL_FORMAT_Y416:
> - return DRM_FORMAT_XVYU16161616;
> - default:
> - case PLANE_CTL_FORMAT_XRGB_8888:
> - if (rgb_order) {
> - if (alpha)
> - return DRM_FORMAT_ABGR8888;
> - else
> - return DRM_FORMAT_XBGR8888;
> - } else {
> - if (alpha)
> - return DRM_FORMAT_ARGB8888;
> - else
> - return DRM_FORMAT_XRGB8888;
> - }
> - case PLANE_CTL_FORMAT_XRGB_2101010:
> - if (rgb_order) {
> - if (alpha)
> - return DRM_FORMAT_ABGR2101010;
> - else
> - return DRM_FORMAT_XBGR2101010;
> - } else {
> - if (alpha)
> - return DRM_FORMAT_ARGB2101010;
> - else
> - return DRM_FORMAT_XRGB2101010;
> - }
> - case PLANE_CTL_FORMAT_XRGB_16161616F:
> - if (rgb_order) {
> - if (alpha)
> - return DRM_FORMAT_ABGR16161616F;
> - else
> - return DRM_FORMAT_XBGR16161616F;
> - } else {
> - if (alpha)
> - return DRM_FORMAT_ARGB16161616F;
> - else
> - return DRM_FORMAT_XRGB16161616F;
> - }
> - }
> -}
> -
> static struct i915_vma *
> initial_plane_vma(struct drm_i915_private *i915,
> struct intel_initial_plane_config *plane_config)
> @@ -2899,52 +2774,6 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
> &to_intel_frontbuffer(fb)->bits);
> }
>
> -
> -static bool
> -skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state,
> - int main_x, int main_y, u32 main_offset,
> - int ccs_plane)
> -{
> - const struct drm_framebuffer *fb = plane_state->hw.fb;
> - int aux_x = plane_state->color_plane[ccs_plane].x;
> - int aux_y = plane_state->color_plane[ccs_plane].y;
> - u32 aux_offset = plane_state->color_plane[ccs_plane].offset;
> - u32 alignment = intel_surf_alignment(fb, ccs_plane);
> - int hsub;
> - int vsub;
> -
> - intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane);
> - while (aux_offset >= main_offset && aux_y <= main_y) {
> - int x, y;
> -
> - if (aux_x == main_x && aux_y == main_y)
> - break;
> -
> - if (aux_offset == 0)
> - break;
> -
> - x = aux_x / hsub;
> - y = aux_y / vsub;
> - aux_offset = intel_plane_adjust_aligned_offset(&x, &y,
> - plane_state,
> - ccs_plane,
> - aux_offset,
> - aux_offset -
> - alignment);
> - aux_x = x * hsub + aux_x % hsub;
> - aux_y = y * vsub + aux_y % vsub;
> - }
> -
> - if (aux_x != main_x || aux_y != main_y)
> - return false;
> -
> - plane_state->color_plane[ccs_plane].offset = aux_offset;
> - plane_state->color_plane[ccs_plane].x = aux_x;
> - plane_state->color_plane[ccs_plane].y = aux_y;
> -
> - return true;
> -}
> -
> unsigned int
> intel_plane_fence_y_offset(const struct intel_plane_state *plane_state)
> {
> @@ -2956,310 +2785,6 @@ intel_plane_fence_y_offset(const struct intel_plane_state *plane_state)
> return y;
> }
>
> -static int intel_plane_min_width(struct intel_plane *plane,
> - const struct drm_framebuffer *fb,
> - int color_plane,
> - unsigned int rotation)
> -{
> - if (plane->min_width)
> - return plane->min_width(fb, color_plane, rotation);
> - else
> - return 1;
> -}
> -
> -static int intel_plane_max_width(struct intel_plane *plane,
> - const struct drm_framebuffer *fb,
> - int color_plane,
> - unsigned int rotation)
> -{
> - if (plane->max_width)
> - return plane->max_width(fb, color_plane, rotation);
> - else
> - return INT_MAX;
> -}
> -
> -static int intel_plane_max_height(struct intel_plane *plane,
> - const struct drm_framebuffer *fb,
> - int color_plane,
> - unsigned int rotation)
> -{
> - if (plane->max_height)
> - return plane->max_height(fb, color_plane, rotation);
> - else
> - return INT_MAX;
> -}
> -
> -int skl_calc_main_surface_offset(const struct intel_plane_state *plane_state,
> - int *x, int *y, u32 *offset)
> -{
> - struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
> - struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> - const struct drm_framebuffer *fb = plane_state->hw.fb;
> - const int aux_plane = intel_main_to_aux_plane(fb, 0);
> - const u32 aux_offset = plane_state->color_plane[aux_plane].offset;
> - const u32 alignment = intel_surf_alignment(fb, 0);
> - const int w = drm_rect_width(&plane_state->uapi.src) >> 16;
> -
> - intel_add_fb_offsets(x, y, plane_state, 0);
> - *offset = intel_plane_compute_aligned_offset(x, y, plane_state, 0);
> - if (drm_WARN_ON(&dev_priv->drm, alignment && !is_power_of_2(alignment)))
> - return -EINVAL;
> -
> - /*
> - * AUX surface offset is specified as the distance from the
> - * main surface offset, and it must be non-negative. Make
> - * sure that is what we will get.
> - */
> - if (aux_plane && *offset > aux_offset)
> - *offset = intel_plane_adjust_aligned_offset(x, y, plane_state, 0,
> - *offset,
> - aux_offset & ~(alignment - 1));
> -
> - /*
> - * When using an X-tiled surface, the plane blows up
> - * if the x offset + width exceed the stride.
> - *
> - * TODO: linear and Y-tiled seem fine, Yf untested,
> - */
> - if (fb->modifier == I915_FORMAT_MOD_X_TILED) {
> - int cpp = fb->format->cpp[0];
> -
> - while ((*x + w) * cpp > plane_state->color_plane[0].stride) {
> - if (*offset == 0) {
> - drm_dbg_kms(&dev_priv->drm,
> - "Unable to find suitable display surface offset due to X-tiling\n");
> - return -EINVAL;
> - }
> -
> - *offset = intel_plane_adjust_aligned_offset(x, y, plane_state, 0,
> - *offset,
> - *offset - alignment);
> - }
> - }
> -
> - return 0;
> -}
> -
> -static int skl_check_main_surface(struct intel_plane_state *plane_state)
> -{
> - struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
> - struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> - const struct drm_framebuffer *fb = plane_state->hw.fb;
> - const unsigned int rotation = plane_state->hw.rotation;
> - int x = plane_state->uapi.src.x1 >> 16;
> - int y = plane_state->uapi.src.y1 >> 16;
> - const int w = drm_rect_width(&plane_state->uapi.src) >> 16;
> - const int h = drm_rect_height(&plane_state->uapi.src) >> 16;
> - const int min_width = intel_plane_min_width(plane, fb, 0, rotation);
> - const int max_width = intel_plane_max_width(plane, fb, 0, rotation);
> - const int max_height = intel_plane_max_height(plane, fb, 0, rotation);
> - const int aux_plane = intel_main_to_aux_plane(fb, 0);
> - const u32 alignment = intel_surf_alignment(fb, 0);
> - u32 offset;
> - int ret;
> -
> - if (w > max_width || w < min_width || h > max_height) {
> - drm_dbg_kms(&dev_priv->drm,
> - "requested Y/RGB source size %dx%d outside limits (min: %dx1 max: %dx%d)\n",
> - w, h, min_width, max_width, max_height);
> - return -EINVAL;
> - }
> -
> - ret = skl_calc_main_surface_offset(plane_state, &x, &y, &offset);
> - if (ret)
> - return ret;
> -
> - /*
> - * CCS AUX surface doesn't have its own x/y offsets, we must make sure
> - * they match with the main surface x/y offsets.
> - */
> - if (is_ccs_modifier(fb->modifier)) {
> - while (!skl_check_main_ccs_coordinates(plane_state, x, y,
> - offset, aux_plane)) {
> - if (offset == 0)
> - break;
> -
> - offset = intel_plane_adjust_aligned_offset(&x, &y, plane_state, 0,
> - offset, offset - alignment);
> - }
> -
> - if (x != plane_state->color_plane[aux_plane].x ||
> - y != plane_state->color_plane[aux_plane].y) {
> - drm_dbg_kms(&dev_priv->drm,
> - "Unable to find suitable display surface offset due to CCS\n");
> - return -EINVAL;
> - }
> - }
> -
> - drm_WARN_ON(&dev_priv->drm, x > 8191 || y > 8191);
> -
> - plane_state->color_plane[0].offset = offset;
> - plane_state->color_plane[0].x = x;
> - plane_state->color_plane[0].y = y;
> -
> - /*
> - * Put the final coordinates back so that the src
> - * coordinate checks will see the right values.
> - */
> - drm_rect_translate_to(&plane_state->uapi.src,
> - x << 16, y << 16);
> -
> - return 0;
> -}
> -
> -static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state)
> -{
> - struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
> - struct drm_i915_private *i915 = to_i915(plane->base.dev);
> - const struct drm_framebuffer *fb = plane_state->hw.fb;
> - unsigned int rotation = plane_state->hw.rotation;
> - int uv_plane = 1;
> - int max_width = intel_plane_max_width(plane, fb, uv_plane, rotation);
> - int max_height = intel_plane_max_height(plane, fb, uv_plane, rotation);
> - int x = plane_state->uapi.src.x1 >> 17;
> - int y = plane_state->uapi.src.y1 >> 17;
> - int w = drm_rect_width(&plane_state->uapi.src) >> 17;
> - int h = drm_rect_height(&plane_state->uapi.src) >> 17;
> - u32 offset;
> -
> - /* FIXME not quite sure how/if these apply to the chroma plane */
> - if (w > max_width || h > max_height) {
> - drm_dbg_kms(&i915->drm,
> - "CbCr source size %dx%d too big (limit %dx%d)\n",
> - w, h, max_width, max_height);
> - return -EINVAL;
> - }
> -
> - intel_add_fb_offsets(&x, &y, plane_state, uv_plane);
> - offset = intel_plane_compute_aligned_offset(&x, &y,
> - plane_state, uv_plane);
> -
> - if (is_ccs_modifier(fb->modifier)) {
> - int ccs_plane = main_to_ccs_plane(fb, uv_plane);
> - u32 aux_offset = plane_state->color_plane[ccs_plane].offset;
> - u32 alignment = intel_surf_alignment(fb, uv_plane);
> -
> - if (offset > aux_offset)
> - offset = intel_plane_adjust_aligned_offset(&x, &y,
> - plane_state,
> - uv_plane,
> - offset,
> - aux_offset & ~(alignment - 1));
> -
> - while (!skl_check_main_ccs_coordinates(plane_state, x, y,
> - offset, ccs_plane)) {
> - if (offset == 0)
> - break;
> -
> - offset = intel_plane_adjust_aligned_offset(&x, &y,
> - plane_state,
> - uv_plane,
> - offset, offset - alignment);
> - }
> -
> - if (x != plane_state->color_plane[ccs_plane].x ||
> - y != plane_state->color_plane[ccs_plane].y) {
> - drm_dbg_kms(&i915->drm,
> - "Unable to find suitable display surface offset due to CCS\n");
> - return -EINVAL;
> - }
> - }
> -
> - drm_WARN_ON(&i915->drm, x > 8191 || y > 8191);
> -
> - plane_state->color_plane[uv_plane].offset = offset;
> - plane_state->color_plane[uv_plane].x = x;
> - plane_state->color_plane[uv_plane].y = y;
> -
> - return 0;
> -}
> -
> -static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state)
> -{
> - const struct drm_framebuffer *fb = plane_state->hw.fb;
> - int src_x = plane_state->uapi.src.x1 >> 16;
> - int src_y = plane_state->uapi.src.y1 >> 16;
> - u32 offset;
> - int ccs_plane;
> -
> - for (ccs_plane = 0; ccs_plane < fb->format->num_planes; ccs_plane++) {
> - int main_hsub, main_vsub;
> - int hsub, vsub;
> - int x, y;
> -
> - if (!is_ccs_plane(fb, ccs_plane) ||
> - is_gen12_ccs_cc_plane(fb, ccs_plane))
> - continue;
> -
> - intel_fb_plane_get_subsampling(&main_hsub, &main_vsub, fb,
> - ccs_to_main_plane(fb, ccs_plane));
> - intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane);
> -
> - hsub *= main_hsub;
> - vsub *= main_vsub;
> - x = src_x / hsub;
> - y = src_y / vsub;
> -
> - intel_add_fb_offsets(&x, &y, plane_state, ccs_plane);
> -
> - offset = intel_plane_compute_aligned_offset(&x, &y,
> - plane_state,
> - ccs_plane);
> -
> - plane_state->color_plane[ccs_plane].offset = offset;
> - plane_state->color_plane[ccs_plane].x = (x * hsub +
> - src_x % hsub) /
> - main_hsub;
> - plane_state->color_plane[ccs_plane].y = (y * vsub +
> - src_y % vsub) /
> - main_vsub;
> - }
> -
> - return 0;
> -}
> -
> -int skl_check_plane_surface(struct intel_plane_state *plane_state)
> -{
> - const struct drm_framebuffer *fb = plane_state->hw.fb;
> - int ret, i;
> -
> - ret = intel_plane_compute_gtt(plane_state);
> - if (ret)
> - return ret;
> -
> - if (!plane_state->uapi.visible)
> - return 0;
> -
> - /*
> - * Handle the AUX surface first since the main surface setup depends on
> - * it.
> - */
> - if (is_ccs_modifier(fb->modifier)) {
> - ret = skl_check_ccs_aux_surface(plane_state);
> - if (ret)
> - return ret;
> - }
> -
> - if (intel_format_info_is_yuv_semiplanar(fb->format,
> - fb->modifier)) {
> - ret = skl_check_nv12_aux_surface(plane_state);
> - if (ret)
> - return ret;
> - }
> -
> - for (i = fb->format->num_planes; i < ARRAY_SIZE(plane_state->color_plane); i++) {
> - plane_state->color_plane[i].offset = 0;
> - plane_state->color_plane[i].x = 0;
> - plane_state->color_plane[i].y = 0;
> - }
> -
> - ret = skl_check_main_surface(plane_state);
> - if (ret)
> - return ret;
> -
> - return 0;
> -}
> -
> static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)
> {
> struct drm_device *dev = intel_crtc->base.dev;
> @@ -3292,307 +2817,6 @@ static void skl_detach_scalers(const struct intel_crtc_state *crtc_state)
> }
> }
>
> -static unsigned int skl_plane_stride_mult(const struct drm_framebuffer *fb,
> - int color_plane, unsigned int rotation)
> -{
> - /*
> - * The stride is either expressed as a multiple of 64 bytes chunks for
> - * linear buffers or in number of tiles for tiled buffers.
> - */
> - if (is_surface_linear(fb, color_plane))
> - return 64;
> - else if (drm_rotation_90_or_270(rotation))
> - return intel_tile_height(fb, color_plane);
> - else
> - return intel_tile_width_bytes(fb, color_plane);
> -}
> -
> -u32 skl_plane_stride(const struct intel_plane_state *plane_state,
> - int color_plane)
> -{
> - const struct drm_framebuffer *fb = plane_state->hw.fb;
> - unsigned int rotation = plane_state->hw.rotation;
> - u32 stride = plane_state->color_plane[color_plane].stride;
> -
> - if (color_plane >= fb->format->num_planes)
> - return 0;
> -
> - return stride / skl_plane_stride_mult(fb, color_plane, rotation);
> -}
> -
> -static u32 skl_plane_ctl_format(u32 pixel_format)
> -{
> - switch (pixel_format) {
> - case DRM_FORMAT_C8:
> - return PLANE_CTL_FORMAT_INDEXED;
> - case DRM_FORMAT_RGB565:
> - return PLANE_CTL_FORMAT_RGB_565;
> - case DRM_FORMAT_XBGR8888:
> - case DRM_FORMAT_ABGR8888:
> - return PLANE_CTL_FORMAT_XRGB_8888 | PLANE_CTL_ORDER_RGBX;
> - case DRM_FORMAT_XRGB8888:
> - case DRM_FORMAT_ARGB8888:
> - return PLANE_CTL_FORMAT_XRGB_8888;
> - case DRM_FORMAT_XBGR2101010:
> - case DRM_FORMAT_ABGR2101010:
> - return PLANE_CTL_FORMAT_XRGB_2101010 | PLANE_CTL_ORDER_RGBX;
> - case DRM_FORMAT_XRGB2101010:
> - case DRM_FORMAT_ARGB2101010:
> - return PLANE_CTL_FORMAT_XRGB_2101010;
> - case DRM_FORMAT_XBGR16161616F:
> - case DRM_FORMAT_ABGR16161616F:
> - return PLANE_CTL_FORMAT_XRGB_16161616F | PLANE_CTL_ORDER_RGBX;
> - case DRM_FORMAT_XRGB16161616F:
> - case DRM_FORMAT_ARGB16161616F:
> - return PLANE_CTL_FORMAT_XRGB_16161616F;
> - case DRM_FORMAT_XYUV8888:
> - return PLANE_CTL_FORMAT_XYUV;
> - case DRM_FORMAT_YUYV:
> - return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_YUYV;
> - case DRM_FORMAT_YVYU:
> - return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_YVYU;
> - case DRM_FORMAT_UYVY:
> - return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_UYVY;
> - case DRM_FORMAT_VYUY:
> - return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_VYUY;
> - case DRM_FORMAT_NV12:
> - return PLANE_CTL_FORMAT_NV12;
> - case DRM_FORMAT_P010:
> - return PLANE_CTL_FORMAT_P010;
> - case DRM_FORMAT_P012:
> - return PLANE_CTL_FORMAT_P012;
> - case DRM_FORMAT_P016:
> - return PLANE_CTL_FORMAT_P016;
> - case DRM_FORMAT_Y210:
> - return PLANE_CTL_FORMAT_Y210;
> - case DRM_FORMAT_Y212:
> - return PLANE_CTL_FORMAT_Y212;
> - case DRM_FORMAT_Y216:
> - return PLANE_CTL_FORMAT_Y216;
> - case DRM_FORMAT_XVYU2101010:
> - return PLANE_CTL_FORMAT_Y410;
> - case DRM_FORMAT_XVYU12_16161616:
> - return PLANE_CTL_FORMAT_Y412;
> - case DRM_FORMAT_XVYU16161616:
> - return PLANE_CTL_FORMAT_Y416;
> - default:
> - MISSING_CASE(pixel_format);
> - }
> -
> - return 0;
> -}
> -
> -static u32 skl_plane_ctl_alpha(const struct intel_plane_state *plane_state)
> -{
> - if (!plane_state->hw.fb->format->has_alpha)
> - return PLANE_CTL_ALPHA_DISABLE;
> -
> - switch (plane_state->hw.pixel_blend_mode) {
> - case DRM_MODE_BLEND_PIXEL_NONE:
> - return PLANE_CTL_ALPHA_DISABLE;
> - case DRM_MODE_BLEND_PREMULTI:
> - return PLANE_CTL_ALPHA_SW_PREMULTIPLY;
> - case DRM_MODE_BLEND_COVERAGE:
> - return PLANE_CTL_ALPHA_HW_PREMULTIPLY;
> - default:
> - MISSING_CASE(plane_state->hw.pixel_blend_mode);
> - return PLANE_CTL_ALPHA_DISABLE;
> - }
> -}
> -
> -static u32 glk_plane_color_ctl_alpha(const struct intel_plane_state *plane_state)
> -{
> - if (!plane_state->hw.fb->format->has_alpha)
> - return PLANE_COLOR_ALPHA_DISABLE;
> -
> - switch (plane_state->hw.pixel_blend_mode) {
> - case DRM_MODE_BLEND_PIXEL_NONE:
> - return PLANE_COLOR_ALPHA_DISABLE;
> - case DRM_MODE_BLEND_PREMULTI:
> - return PLANE_COLOR_ALPHA_SW_PREMULTIPLY;
> - case DRM_MODE_BLEND_COVERAGE:
> - return PLANE_COLOR_ALPHA_HW_PREMULTIPLY;
> - default:
> - MISSING_CASE(plane_state->hw.pixel_blend_mode);
> - return PLANE_COLOR_ALPHA_DISABLE;
> - }
> -}
> -
> -static u32 skl_plane_ctl_tiling(u64 fb_modifier)
> -{
> - switch (fb_modifier) {
> - case DRM_FORMAT_MOD_LINEAR:
> - break;
> - case I915_FORMAT_MOD_X_TILED:
> - return PLANE_CTL_TILED_X;
> - case I915_FORMAT_MOD_Y_TILED:
> - return PLANE_CTL_TILED_Y;
> - case I915_FORMAT_MOD_Y_TILED_CCS:
> - case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
> - return PLANE_CTL_TILED_Y | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
> - case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
> - return PLANE_CTL_TILED_Y |
> - PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
> - PLANE_CTL_CLEAR_COLOR_DISABLE;
> - case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
> - return PLANE_CTL_TILED_Y | PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE;
> - case I915_FORMAT_MOD_Yf_TILED:
> - return PLANE_CTL_TILED_YF;
> - case I915_FORMAT_MOD_Yf_TILED_CCS:
> - return PLANE_CTL_TILED_YF | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
> - default:
> - MISSING_CASE(fb_modifier);
> - }
> -
> - return 0;
> -}
> -
> -static u32 skl_plane_ctl_rotate(unsigned int rotate)
> -{
> - switch (rotate) {
> - case DRM_MODE_ROTATE_0:
> - break;
> - /*
> - * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr
> - * while i915 HW rotation is clockwise, thats why this swapping.
> - */
> - case DRM_MODE_ROTATE_90:
> - return PLANE_CTL_ROTATE_270;
> - case DRM_MODE_ROTATE_180:
> - return PLANE_CTL_ROTATE_180;
> - case DRM_MODE_ROTATE_270:
> - return PLANE_CTL_ROTATE_90;
> - default:
> - MISSING_CASE(rotate);
> - }
> -
> - return 0;
> -}
> -
> -static u32 cnl_plane_ctl_flip(unsigned int reflect)
> -{
> - switch (reflect) {
> - case 0:
> - break;
> - case DRM_MODE_REFLECT_X:
> - return PLANE_CTL_FLIP_HORIZONTAL;
> - case DRM_MODE_REFLECT_Y:
> - default:
> - MISSING_CASE(reflect);
> - }
> -
> - return 0;
> -}
> -
> -u32 skl_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
> -{
> - struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
> - u32 plane_ctl = 0;
> -
> - if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
> - return plane_ctl;
> -
> - if (crtc_state->gamma_enable)
> - plane_ctl |= PLANE_CTL_PIPE_GAMMA_ENABLE;
> -
> - if (crtc_state->csc_enable)
> - plane_ctl |= PLANE_CTL_PIPE_CSC_ENABLE;
> -
> - return plane_ctl;
> -}
> -
> -u32 skl_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;
> - const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
> - u32 plane_ctl;
> -
> - plane_ctl = PLANE_CTL_ENABLE;
> -
> - if (INTEL_GEN(dev_priv) < 10 && !IS_GEMINILAKE(dev_priv)) {
> - plane_ctl |= skl_plane_ctl_alpha(plane_state);
> - plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE;
> -
> - if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
> - plane_ctl |= PLANE_CTL_YUV_TO_RGB_CSC_FORMAT_BT709;
> -
> - if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
> - plane_ctl |= PLANE_CTL_YUV_RANGE_CORRECTION_DISABLE;
> - }
> -
> - plane_ctl |= skl_plane_ctl_format(fb->format->format);
> - plane_ctl |= skl_plane_ctl_tiling(fb->modifier);
> - plane_ctl |= skl_plane_ctl_rotate(rotation & DRM_MODE_ROTATE_MASK);
> -
> - if (INTEL_GEN(dev_priv) >= 10)
> - plane_ctl |= cnl_plane_ctl_flip(rotation &
> - DRM_MODE_REFLECT_MASK);
> -
> - if (key->flags & I915_SET_COLORKEY_DESTINATION)
> - plane_ctl |= PLANE_CTL_KEY_ENABLE_DESTINATION;
> - else if (key->flags & I915_SET_COLORKEY_SOURCE)
> - plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE;
> -
> - return plane_ctl;
> -}
> -
> -u32 glk_plane_color_ctl_crtc(const struct intel_crtc_state *crtc_state)
> -{
> - struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
> - u32 plane_color_ctl = 0;
> -
> - if (INTEL_GEN(dev_priv) >= 11)
> - return plane_color_ctl;
> -
> - if (crtc_state->gamma_enable)
> - plane_color_ctl |= PLANE_COLOR_PIPE_GAMMA_ENABLE;
> -
> - if (crtc_state->csc_enable)
> - plane_color_ctl |= PLANE_COLOR_PIPE_CSC_ENABLE;
> -
> - return plane_color_ctl;
> -}
> -
> -u32 glk_plane_color_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;
> - struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
> - u32 plane_color_ctl = 0;
> -
> - plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE;
> - plane_color_ctl |= glk_plane_color_ctl_alpha(plane_state);
> -
> - if (fb->format->is_yuv && !icl_is_hdr_plane(dev_priv, plane->id)) {
> - switch (plane_state->hw.color_encoding) {
> - case DRM_COLOR_YCBCR_BT709:
> - plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709;
> - break;
> - case DRM_COLOR_YCBCR_BT2020:
> - plane_color_ctl |=
> - PLANE_COLOR_CSC_MODE_YUV2020_TO_RGB2020;
> - break;
> - default:
> - plane_color_ctl |=
> - PLANE_COLOR_CSC_MODE_YUV601_TO_RGB601;
> - }
> - if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
> - plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE;
> - } else if (fb->format->is_yuv) {
> - plane_color_ctl |= PLANE_COLOR_INPUT_CSC_ENABLE;
> - if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
> - plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE;
> - }
> -
> - return plane_color_ctl;
> -}
> -
> static int
> __intel_display_resume(struct drm_device *dev,
> struct drm_atomic_state *state,
> @@ -8276,150 +7500,6 @@ static void skl_get_pfit_config(struct intel_crtc_state *crtc_state)
> scaler_state->scaler_users &= ~(1 << SKL_CRTC_INDEX);
> }
>
> -static void
> -skl_get_initial_plane_config(struct intel_crtc *crtc,
> - struct intel_initial_plane_config *plane_config)
> -{
> - struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state);
> - struct drm_device *dev = crtc->base.dev;
> - struct drm_i915_private *dev_priv = to_i915(dev);
> - struct intel_plane *plane = to_intel_plane(crtc->base.primary);
> - enum plane_id plane_id = plane->id;
> - enum pipe pipe;
> - u32 val, base, offset, stride_mult, tiling, alpha;
> - int fourcc, pixel_format;
> - unsigned int aligned_height;
> - struct drm_framebuffer *fb;
> - struct intel_framebuffer *intel_fb;
> -
> - if (!plane->get_hw_state(plane, &pipe))
> - return;
> -
> - drm_WARN_ON(dev, pipe != crtc->pipe);
> -
> - if (crtc_state->bigjoiner) {
> - drm_dbg_kms(&dev_priv->drm,
> - "Unsupported bigjoiner configuration for initial FB\n");
> - return;
> - }
> -
> - intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
> - if (!intel_fb) {
> - drm_dbg_kms(&dev_priv->drm, "failed to alloc fb\n");
> - return;
> - }
> -
> - fb = &intel_fb->base;
> -
> - fb->dev = dev;
> -
> - val = intel_de_read(dev_priv, PLANE_CTL(pipe, plane_id));
> -
> - if (INTEL_GEN(dev_priv) >= 11)
> - pixel_format = val & ICL_PLANE_CTL_FORMAT_MASK;
> - else
> - pixel_format = val & PLANE_CTL_FORMAT_MASK;
> -
> - if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) {
> - alpha = intel_de_read(dev_priv,
> - PLANE_COLOR_CTL(pipe, plane_id));
> - alpha &= PLANE_COLOR_ALPHA_MASK;
> - } else {
> - alpha = val & PLANE_CTL_ALPHA_MASK;
> - }
> -
> - fourcc = skl_format_to_fourcc(pixel_format,
> - val & PLANE_CTL_ORDER_RGBX, alpha);
> - fb->format = drm_format_info(fourcc);
> -
> - tiling = val & PLANE_CTL_TILED_MASK;
> - switch (tiling) {
> - case PLANE_CTL_TILED_LINEAR:
> - fb->modifier = DRM_FORMAT_MOD_LINEAR;
> - break;
> - case PLANE_CTL_TILED_X:
> - plane_config->tiling = I915_TILING_X;
> - fb->modifier = I915_FORMAT_MOD_X_TILED;
> - break;
> - case PLANE_CTL_TILED_Y:
> - plane_config->tiling = I915_TILING_Y;
> - if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
> - fb->modifier = INTEL_GEN(dev_priv) >= 12 ?
> - I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS :
> - I915_FORMAT_MOD_Y_TILED_CCS;
> - else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE)
> - fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS;
> - else
> - fb->modifier = I915_FORMAT_MOD_Y_TILED;
> - break;
> - case PLANE_CTL_TILED_YF:
> - if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
> - fb->modifier = I915_FORMAT_MOD_Yf_TILED_CCS;
> - else
> - fb->modifier = I915_FORMAT_MOD_Yf_TILED;
> - break;
> - default:
> - MISSING_CASE(tiling);
> - goto error;
> - }
> -
> - /*
> - * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr
> - * while i915 HW rotation is clockwise, thats why this swapping.
> - */
> - switch (val & PLANE_CTL_ROTATE_MASK) {
> - case PLANE_CTL_ROTATE_0:
> - plane_config->rotation = DRM_MODE_ROTATE_0;
> - break;
> - case PLANE_CTL_ROTATE_90:
> - plane_config->rotation = DRM_MODE_ROTATE_270;
> - break;
> - case PLANE_CTL_ROTATE_180:
> - plane_config->rotation = DRM_MODE_ROTATE_180;
> - break;
> - case PLANE_CTL_ROTATE_270:
> - plane_config->rotation = DRM_MODE_ROTATE_90;
> - break;
> - }
> -
> - if (INTEL_GEN(dev_priv) >= 10 &&
> - val & PLANE_CTL_FLIP_HORIZONTAL)
> - plane_config->rotation |= DRM_MODE_REFLECT_X;
> -
> - /* 90/270 degree rotation would require extra work */
> - if (drm_rotation_90_or_270(plane_config->rotation))
> - goto error;
> -
> - base = intel_de_read(dev_priv, PLANE_SURF(pipe, plane_id)) & 0xfffff000;
> - plane_config->base = base;
> -
> - offset = intel_de_read(dev_priv, PLANE_OFFSET(pipe, plane_id));
> -
> - val = intel_de_read(dev_priv, PLANE_SIZE(pipe, plane_id));
> - fb->height = ((val >> 16) & 0xffff) + 1;
> - fb->width = ((val >> 0) & 0xffff) + 1;
> -
> - val = intel_de_read(dev_priv, PLANE_STRIDE(pipe, plane_id));
> - stride_mult = skl_plane_stride_mult(fb, 0, DRM_MODE_ROTATE_0);
> - fb->pitches[0] = (val & 0x3ff) * stride_mult;
> -
> - aligned_height = intel_fb_align_height(fb, 0, fb->height);
> -
> - plane_config->size = fb->pitches[0] * aligned_height;
> -
> - drm_dbg_kms(&dev_priv->drm,
> - "%s/%s with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
> - crtc->base.name, plane->base.name, fb->width, fb->height,
> - fb->format->cpp[0] * 8, base, fb->pitches[0],
> - plane_config->size);
> -
> - plane_config->fb = intel_fb;
> - return;
> -
> -error:
> - kfree(intel_fb);
> -}
> -
> static void ilk_get_pfit_config(struct intel_crtc_state *crtc_state)
> {
> struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
> index c72e41b61349..3c153eb78092 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.h
> +++ b/drivers/gpu/drm/i915/display/intel_display.h
> @@ -52,6 +52,7 @@ struct intel_crtc_state;
> struct intel_digital_port;
> struct intel_dp;
> struct intel_encoder;
> +struct intel_initial_plane_config;
> struct intel_load_detect_pipe;
> struct intel_plane;
> struct intel_plane_state;
> @@ -517,7 +518,6 @@ void intel_link_compute_m_n(u16 bpp, int nlanes,
> struct intel_link_m_n *m_n,
> bool constant_n, bool fec_enable);
> bool is_ccs_modifier(u64 modifier);
> -int intel_main_to_aux_plane(const struct drm_framebuffer *fb, int main_plane);
> void lpt_disable_clkout_dp(struct drm_i915_private *dev_priv);
> u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv,
> u32 pixel_format, u64 modifier);
> @@ -629,18 +629,7 @@ u32 skl_scaler_get_filter_select(enum drm_scaling_filter filter, int set);
> void skl_scaler_setup_filter(struct drm_i915_private *dev_priv, enum pipe pipe,
> int id, int set, enum drm_scaling_filter filter);
> void ilk_pfit_disable(const struct intel_crtc_state *old_crtc_state);
> -u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state,
> - const struct intel_plane_state *plane_state);
> -u32 glk_plane_color_ctl_crtc(const struct intel_crtc_state *crtc_state);
> -u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state,
> - const struct intel_plane_state *plane_state);
> -u32 skl_plane_ctl_crtc(const struct intel_crtc_state *crtc_state);
> -u32 skl_plane_stride(const struct intel_plane_state *plane_state,
> - int plane);
> -int skl_check_plane_surface(struct intel_plane_state *plane_state);
> -int skl_calc_main_surface_offset(const struct intel_plane_state *plane_state,
> - int *x, int *y, u32 *offset);
> -int skl_format_to_fourcc(int format, bool rgb_order, bool alpha);
> +
> int bdw_get_pipemisc_bpp(struct intel_crtc *crtc);
> unsigned int intel_plane_fence_y_offset(const struct intel_plane_state *plane_state);
>
> @@ -663,6 +652,18 @@ struct intel_encoder *
> intel_get_crtc_new_encoder(const struct intel_atomic_state *state,
> const struct intel_crtc_state *crtc_state);
>
> +unsigned int intel_surf_alignment(const struct drm_framebuffer *fb,
> + int color_plane);
> +void intel_fb_plane_get_subsampling(int *hsub, int *vsub,
> + const struct drm_framebuffer *fb,
> + int color_plane);
> +u32 intel_plane_adjust_aligned_offset(int *x, int *y,
> + const struct intel_plane_state *state,
> + int color_plane,
> + u32 old_offset, u32 new_offset);
> +unsigned int intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane);
> +unsigned int intel_tile_height(const struct drm_framebuffer *fb, int color_plane);
> +
> /* modesetting */
> void intel_modeset_init_hw(struct drm_i915_private *i915);
> int intel_modeset_init_noirq(struct drm_i915_private *i915);
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
> index 307ff4b771f4..6183f2f0424b 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -37,6 +37,7 @@
> #include <drm/drm_dp_mst_helper.h>
> #include <drm/drm_encoder.h>
> #include <drm/drm_fb_helper.h>
> +#include <drm/drm_fourcc.h>
> #include <drm/drm_probe_helper.h>
> #include <drm/drm_rect.h>
> #include <drm/drm_vblank.h>
> @@ -1945,4 +1946,30 @@ static inline u32 intel_fdi_link_freq(struct drm_i915_private *dev_priv,
> return dev_priv->fdi_pll_freq;
> }
>
> +static inline bool is_ccs_plane(const struct drm_framebuffer *fb, int plane)
> +{
> + if (!is_ccs_modifier(fb->modifier))
> + return false;
> +
> + return plane >= fb->format->num_planes / 2;
> +}
> +
> +static inline bool is_gen12_ccs_modifier(u64 modifier)
> +{
> + return modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS ||
> + modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC ||
> + modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS;
> +}
> +
> +static inline bool is_gen12_ccs_plane(const struct drm_framebuffer *fb, int plane)
> +{
> + return is_gen12_ccs_modifier(fb->modifier) && is_ccs_plane(fb, plane);
> +}
> +
> +static inline bool is_gen12_ccs_cc_plane(const struct drm_framebuffer *fb, int plane)
> +{
> + return fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC &&
> + plane == 2;
> +}
> +
> #endif /* __INTEL_DISPLAY_TYPES_H__ */
> diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
> index 28423356d53b..bf214d0e2dec 100644
> --- a/drivers/gpu/drm/i915/display/intel_psr.c
> +++ b/drivers/gpu/drm/i915/display/intel_psr.c
> @@ -32,6 +32,7 @@
> #include "intel_hdmi.h"
> #include "intel_psr.h"
> #include "intel_sprite.h"
> +#include "skl_universal_plane.h"
>
> /**
> * DOC: Panel Self Refresh (PSR/SRD)
> diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c
> index 26025251b038..93f3afc245b9 100644
> --- a/drivers/gpu/drm/i915/display/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/display/intel_sprite.c
> @@ -376,212 +376,7 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
> return 0;
> }
>
> -static u8 icl_nv12_y_plane_mask(struct drm_i915_private *i915)
> -{
> - if (HAS_D12_PLANE_MINIMIZATION(i915))
> - return BIT(PLANE_SPRITE2) | BIT(PLANE_SPRITE3);
> - else
> - return BIT(PLANE_SPRITE4) | BIT(PLANE_SPRITE5);
> -}
> -
> -bool icl_is_nv12_y_plane(struct drm_i915_private *dev_priv,
> - enum plane_id plane_id)
> -{
> - return INTEL_GEN(dev_priv) >= 11 &&
> - icl_nv12_y_plane_mask(dev_priv) & BIT(plane_id);
> -}
> -
> -bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id)
> -{
> - return INTEL_GEN(dev_priv) >= 11 &&
> - icl_hdr_plane_mask() & BIT(plane_id);
> -}
> -
> -static void
> -skl_plane_ratio(const struct intel_crtc_state *crtc_state,
> - const struct intel_plane_state *plane_state,
> - unsigned int *num, unsigned int *den)
> -{
> - struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev);
> - const struct drm_framebuffer *fb = plane_state->hw.fb;
> -
> - if (fb->format->cpp[0] == 8) {
> - if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) {
> - *num = 10;
> - *den = 8;
> - } else {
> - *num = 9;
> - *den = 8;
> - }
> - } else {
> - *num = 1;
> - *den = 1;
> - }
> -}
> -
> -static int skl_plane_min_cdclk(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);
> - unsigned int num, den;
> - unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
> -
> - skl_plane_ratio(crtc_state, plane_state, &num, &den);
> -
> - /* two pixels per clock on glk+ */
> - if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
> - den *= 2;
> -
> - return DIV_ROUND_UP(pixel_rate * num, den);
> -}
> -
> -static int skl_plane_max_width(const struct drm_framebuffer *fb,
> - int color_plane,
> - unsigned int rotation)
> -{
> - int cpp = fb->format->cpp[color_plane];
> -
> - switch (fb->modifier) {
> - case DRM_FORMAT_MOD_LINEAR:
> - case I915_FORMAT_MOD_X_TILED:
> - /*
> - * Validated limit is 4k, but has 5k should
> - * work apart from the following features:
> - * - Ytile (already limited to 4k)
> - * - FP16 (already limited to 4k)
> - * - render compression (already limited to 4k)
> - * - KVMR sprite and cursor (don't care)
> - * - horizontal panning (TODO verify this)
> - * - pipe and plane scaling (TODO verify this)
> - */
> - if (cpp == 8)
> - return 4096;
> - else
> - return 5120;
> - case I915_FORMAT_MOD_Y_TILED_CCS:
> - case I915_FORMAT_MOD_Yf_TILED_CCS:
> - case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
> - /* FIXME AUX plane? */
> - case I915_FORMAT_MOD_Y_TILED:
> - case I915_FORMAT_MOD_Yf_TILED:
> - if (cpp == 8)
> - return 2048;
> - else
> - return 4096;
> - default:
> - MISSING_CASE(fb->modifier);
> - return 2048;
> - }
> -}
> -
> -static int glk_plane_max_width(const struct drm_framebuffer *fb,
> - int color_plane,
> - unsigned int rotation)
> -{
> - int cpp = fb->format->cpp[color_plane];
> -
> - switch (fb->modifier) {
> - case DRM_FORMAT_MOD_LINEAR:
> - case I915_FORMAT_MOD_X_TILED:
> - if (cpp == 8)
> - return 4096;
> - else
> - return 5120;
> - case I915_FORMAT_MOD_Y_TILED_CCS:
> - case I915_FORMAT_MOD_Yf_TILED_CCS:
> - /* FIXME AUX plane? */
> - case I915_FORMAT_MOD_Y_TILED:
> - case I915_FORMAT_MOD_Yf_TILED:
> - if (cpp == 8)
> - return 2048;
> - else
> - return 5120;
> - default:
> - MISSING_CASE(fb->modifier);
> - return 2048;
> - }
> -}
> -
> -static int icl_plane_min_width(const struct drm_framebuffer *fb,
> - int color_plane,
> - unsigned int rotation)
> -{
> - /* Wa_14011264657, Wa_14011050563: gen11+ */
> - switch (fb->format->format) {
> - case DRM_FORMAT_C8:
> - return 18;
> - case DRM_FORMAT_RGB565:
> - return 10;
> - 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_XVYU2101010:
> - case DRM_FORMAT_Y212:
> - case DRM_FORMAT_Y216:
> - return 6;
> - case DRM_FORMAT_NV12:
> - return 20;
> - case DRM_FORMAT_P010:
> - case DRM_FORMAT_P012:
> - case DRM_FORMAT_P016:
> - return 12;
> - case DRM_FORMAT_XRGB16161616F:
> - case DRM_FORMAT_XBGR16161616F:
> - case DRM_FORMAT_ARGB16161616F:
> - case DRM_FORMAT_ABGR16161616F:
> - case DRM_FORMAT_XVYU12_16161616:
> - case DRM_FORMAT_XVYU16161616:
> - return 4;
> - default:
> - return 1;
> - }
> -}
> -
> -static int icl_plane_max_width(const struct drm_framebuffer *fb,
> - int color_plane,
> - unsigned int rotation)
> -{
> - return 5120;
> -}
> -
> -static int skl_plane_max_height(const struct drm_framebuffer *fb,
> - int color_plane,
> - unsigned int rotation)
> -{
> - return 4096;
> -}
> -
> -static int icl_plane_max_height(const struct drm_framebuffer *fb,
> - int color_plane,
> - unsigned int rotation)
> -{
> - return 4320;
> -}
> -
> -static unsigned int
> -skl_plane_max_stride(struct intel_plane *plane,
> - u32 pixel_format, u64 modifier,
> - unsigned int rotation)
> -{
> - const struct drm_format_info *info = drm_format_info(pixel_format);
> - int cpp = info->cpp[0];
> -
> - /*
> - * "The stride in bytes must not exceed the
> - * of the size of 8K pixels and 32K bytes."
> - */
> - if (drm_rotation_90_or_270(rotation))
> - return min(8192, 32768 / cpp);
> - else
> - return min(8192 * cpp, 32768);
> -}
> -
> -static void
> +void
> skl_program_scaler(struct intel_plane *plane,
> const struct intel_crtc_state *crtc_state,
> const struct intel_plane_state *plane_state)
> @@ -643,317 +438,6 @@ skl_program_scaler(struct intel_plane *plane,
> (crtc_w << 16) | crtc_h);
> }
>
> -/* Preoffset values for YUV to RGB Conversion */
> -#define PREOFF_YUV_TO_RGB_HI 0x1800
> -#define PREOFF_YUV_TO_RGB_ME 0x0000
> -#define PREOFF_YUV_TO_RGB_LO 0x1800
> -
> -#define ROFF(x) (((x) & 0xffff) << 16)
> -#define GOFF(x) (((x) & 0xffff) << 0)
> -#define BOFF(x) (((x) & 0xffff) << 16)
> -
> -/*
> - * Programs the input color space conversion stage for ICL HDR planes.
> - * Note that it is assumed that this stage always happens after YUV
> - * range correction. Thus, the input to this stage is assumed to be
> - * in full-range YCbCr.
> - */
> -static void
> -icl_program_input_csc(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 pipe pipe = plane->pipe;
> - enum plane_id plane_id = plane->id;
> -
> - static const u16 input_csc_matrix[][9] = {
> - /*
> - * BT.601 full range YCbCr -> full range RGB
> - * The matrix required is :
> - * [1.000, 0.000, 1.371,
> - * 1.000, -0.336, -0.698,
> - * 1.000, 1.732, 0.0000]
> - */
> - [DRM_COLOR_YCBCR_BT601] = {
> - 0x7AF8, 0x7800, 0x0,
> - 0x8B28, 0x7800, 0x9AC0,
> - 0x0, 0x7800, 0x7DD8,
> - },
> - /*
> - * BT.709 full range YCbCr -> full range RGB
> - * The matrix required is :
> - * [1.000, 0.000, 1.574,
> - * 1.000, -0.187, -0.468,
> - * 1.000, 1.855, 0.0000]
> - */
> - [DRM_COLOR_YCBCR_BT709] = {
> - 0x7C98, 0x7800, 0x0,
> - 0x9EF8, 0x7800, 0xAC00,
> - 0x0, 0x7800, 0x7ED8,
> - },
> - /*
> - * BT.2020 full range YCbCr -> full range RGB
> - * The matrix required is :
> - * [1.000, 0.000, 1.474,
> - * 1.000, -0.1645, -0.5713,
> - * 1.000, 1.8814, 0.0000]
> - */
> - [DRM_COLOR_YCBCR_BT2020] = {
> - 0x7BC8, 0x7800, 0x0,
> - 0x8928, 0x7800, 0xAA88,
> - 0x0, 0x7800, 0x7F10,
> - },
> - };
> - const u16 *csc = input_csc_matrix[plane_state->hw.color_encoding];
> -
> - intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 0),
> - ROFF(csc[0]) | GOFF(csc[1]));
> - intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 1),
> - BOFF(csc[2]));
> - intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 2),
> - ROFF(csc[3]) | GOFF(csc[4]));
> - intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 3),
> - BOFF(csc[5]));
> - intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 4),
> - ROFF(csc[6]) | GOFF(csc[7]));
> - intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 5),
> - BOFF(csc[8]));
> -
> - intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 0),
> - PREOFF_YUV_TO_RGB_HI);
> - intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1),
> - PREOFF_YUV_TO_RGB_ME);
> - intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 2),
> - PREOFF_YUV_TO_RGB_LO);
> - intel_de_write_fw(dev_priv,
> - PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 0), 0x0);
> - intel_de_write_fw(dev_priv,
> - PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 1), 0x0);
> - intel_de_write_fw(dev_priv,
> - PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 2), 0x0);
> -}
> -
> -static void
> -skl_plane_async_flip(struct intel_plane *plane,
> - const struct intel_crtc_state *crtc_state,
> - const struct intel_plane_state *plane_state,
> - bool async_flip)
> -{
> - struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> - unsigned long irqflags;
> - enum plane_id plane_id = plane->id;
> - enum pipe pipe = plane->pipe;
> - u32 surf_addr = plane_state->color_plane[0].offset;
> - u32 plane_ctl = plane_state->ctl;
> -
> - plane_ctl |= skl_plane_ctl_crtc(crtc_state);
> -
> - if (async_flip)
> - plane_ctl |= PLANE_CTL_ASYNC_FLIP;
> -
> - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
> -
> - intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
> - intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
> - intel_plane_ggtt_offset(plane_state) + surf_addr);
> -
> - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
> -}
> -
> -static void
> -skl_program_plane(struct intel_plane *plane,
> - const struct intel_crtc_state *crtc_state,
> - const struct intel_plane_state *plane_state,
> - int color_plane)
> -{
> - struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> - enum plane_id plane_id = plane->id;
> - enum pipe pipe = plane->pipe;
> - const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
> - u32 surf_addr = plane_state->color_plane[color_plane].offset;
> - u32 stride = skl_plane_stride(plane_state, color_plane);
> - const struct drm_framebuffer *fb = plane_state->hw.fb;
> - int aux_plane = intel_main_to_aux_plane(fb, color_plane);
> - int crtc_x = plane_state->uapi.dst.x1;
> - int crtc_y = plane_state->uapi.dst.y1;
> - u32 x = plane_state->color_plane[color_plane].x;
> - u32 y = plane_state->color_plane[color_plane].y;
> - u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
> - u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
> - u8 alpha = plane_state->hw.alpha >> 8;
> - u32 plane_color_ctl = 0, aux_dist = 0;
> - unsigned long irqflags;
> - u32 keymsk, keymax;
> - u32 plane_ctl = plane_state->ctl;
> -
> - plane_ctl |= skl_plane_ctl_crtc(crtc_state);
> -
> - if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
> - plane_color_ctl = plane_state->color_ctl |
> - glk_plane_color_ctl_crtc(crtc_state);
> -
> - /* Sizes are 0 based */
> - src_w--;
> - src_h--;
> -
> - keymax = (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha);
> -
> - keymsk = key->channel_mask & 0x7ffffff;
> - if (alpha < 0xff)
> - keymsk |= PLANE_KEYMSK_ALPHA_ENABLE;
> -
> - /* The scaler will handle the output position */
> - if (plane_state->scaler_id >= 0) {
> - crtc_x = 0;
> - crtc_y = 0;
> - }
> -
> - if (aux_plane) {
> - aux_dist = plane_state->color_plane[aux_plane].offset - surf_addr;
> -
> - if (INTEL_GEN(dev_priv) < 12)
> - aux_dist |= skl_plane_stride(plane_state, aux_plane);
> - }
> -
> - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
> -
> - intel_de_write_fw(dev_priv, PLANE_STRIDE(pipe, plane_id), stride);
> - intel_de_write_fw(dev_priv, PLANE_POS(pipe, plane_id),
> - (crtc_y << 16) | crtc_x);
> - intel_de_write_fw(dev_priv, PLANE_SIZE(pipe, plane_id),
> - (src_h << 16) | src_w);
> -
> - intel_de_write_fw(dev_priv, PLANE_AUX_DIST(pipe, plane_id), aux_dist);
> -
> - if (icl_is_hdr_plane(dev_priv, plane_id))
> - intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id),
> - plane_state->cus_ctl);
> -
> - if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
> - intel_de_write_fw(dev_priv, PLANE_COLOR_CTL(pipe, plane_id),
> - plane_color_ctl);
> -
> - if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id))
> - icl_program_input_csc(plane, crtc_state, plane_state);
> -
> - if (fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC)
> - intel_uncore_write64_fw(&dev_priv->uncore,
> - PLANE_CC_VAL(pipe, plane_id), plane_state->ccval);
> -
> - skl_write_plane_wm(plane, crtc_state);
> -
> - intel_de_write_fw(dev_priv, PLANE_KEYVAL(pipe, plane_id),
> - key->min_value);
> - intel_de_write_fw(dev_priv, PLANE_KEYMSK(pipe, plane_id), keymsk);
> - intel_de_write_fw(dev_priv, PLANE_KEYMAX(pipe, plane_id), keymax);
> -
> - intel_de_write_fw(dev_priv, PLANE_OFFSET(pipe, plane_id),
> - (y << 16) | x);
> -
> - if (INTEL_GEN(dev_priv) < 11)
> - intel_de_write_fw(dev_priv, PLANE_AUX_OFFSET(pipe, plane_id),
> - (plane_state->color_plane[1].y << 16) | plane_state->color_plane[1].x);
> -
> - if (!drm_atomic_crtc_needs_modeset(&crtc_state->uapi))
> - intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, color_plane);
> -
> - /*
> - * 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, PLANE_CTL(pipe, plane_id), plane_ctl);
> - intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
> - intel_plane_ggtt_offset(plane_state) + surf_addr);
> -
> - if (plane_state->scaler_id >= 0)
> - skl_program_scaler(plane, crtc_state, plane_state);
> -
> - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
> -}
> -
> -static void
> -skl_update_plane(struct intel_plane *plane,
> - const struct intel_crtc_state *crtc_state,
> - const struct intel_plane_state *plane_state)
> -{
> - int color_plane = 0;
> -
> - if (plane_state->planar_linked_plane && !plane_state->planar_slave)
> - /* Program the UV plane on planar master */
> - color_plane = 1;
> -
> - skl_program_plane(plane, crtc_state, plane_state, color_plane);
> -}
> -static void
> -skl_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 plane_id plane_id = plane->id;
> - enum pipe pipe = plane->pipe;
> - unsigned long irqflags;
> -
> - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
> -
> - if (icl_is_hdr_plane(dev_priv, plane_id))
> - intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id), 0);
> -
> - skl_write_plane_wm(plane, crtc_state);
> -
> - intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), 0);
> - intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), 0);
> -
> - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
> -}
> -
> -static bool
> -skl_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 plane_id plane_id = plane->id;
> - intel_wakeref_t wakeref;
> - bool ret;
> -
> - power_domain = POWER_DOMAIN_PIPE(plane->pipe);
> - wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> - if (!wakeref)
> - return false;
> -
> - ret = intel_de_read(dev_priv, PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;
> -
> - *pipe = plane->pipe;
> -
> - intel_display_power_put(dev_priv, power_domain, wakeref);
> -
> - return ret;
> -}
> -
> -static void
> -skl_plane_enable_flip_done(struct intel_plane *plane)
> -{
> - struct drm_i915_private *i915 = to_i915(plane->base.dev);
> - enum pipe pipe = plane->pipe;
> -
> - spin_lock_irq(&i915->irq_lock);
> - bdw_enable_pipe_irq(i915, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id));
> - spin_unlock_irq(&i915->irq_lock);
> -}
> -
> -static void
> -skl_plane_disable_flip_done(struct intel_plane *plane)
> -{
> - struct drm_i915_private *i915 = to_i915(plane->base.dev);
> - enum pipe pipe = plane->pipe;
> -
> - spin_lock_irq(&i915->irq_lock);
> - bdw_disable_pipe_irq(i915, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id));
> - spin_unlock_irq(&i915->irq_lock);
> -}
> -
> static void i9xx_plane_linear_gamma(u16 gamma[8])
> {
> /* The points are not evenly spaced. */
> @@ -2297,253 +1781,19 @@ vlv_sprite_check(struct intel_crtc_state *crtc_state,
> return 0;
> }
>
> -static bool intel_format_is_p01x(u32 format)
> +static bool has_dst_key_in_primary_plane(struct drm_i915_private *dev_priv)
> {
> - switch (format) {
> - case DRM_FORMAT_P010:
> - case DRM_FORMAT_P012:
> - case DRM_FORMAT_P016:
> - return true;
> - default:
> - return false;
> - }
> + return INTEL_GEN(dev_priv) >= 9;
> }
>
> -static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
> - const struct intel_plane_state *plane_state)
> +static void intel_plane_set_ckey(struct intel_plane_state *plane_state,
> + const struct drm_intel_sprite_colorkey *set)
> {
> struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
> struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> - const struct drm_framebuffer *fb = plane_state->hw.fb;
> - unsigned int rotation = plane_state->hw.rotation;
> - struct drm_format_name_buf format_name;
> + struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
>
> - if (!fb)
> - return 0;
> -
> - if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) &&
> - is_ccs_modifier(fb->modifier)) {
> - drm_dbg_kms(&dev_priv->drm,
> - "RC support only with 0/180 degree rotation (%x)\n",
> - rotation);
> - return -EINVAL;
> - }
> -
> - if (rotation & DRM_MODE_REFLECT_X &&
> - fb->modifier == DRM_FORMAT_MOD_LINEAR) {
> - drm_dbg_kms(&dev_priv->drm,
> - "horizontal flip is not supported with linear surface formats\n");
> - return -EINVAL;
> - }
> -
> - if (drm_rotation_90_or_270(rotation)) {
> - if (fb->modifier != I915_FORMAT_MOD_Y_TILED &&
> - fb->modifier != I915_FORMAT_MOD_Yf_TILED) {
> - drm_dbg_kms(&dev_priv->drm,
> - "Y/Yf tiling required for 90/270!\n");
> - return -EINVAL;
> - }
> -
> - /*
> - * 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.
> - */
> - switch (fb->format->format) {
> - case DRM_FORMAT_RGB565:
> - if (INTEL_GEN(dev_priv) >= 11)
> - break;
> - fallthrough;
> - 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_dbg_kms(&dev_priv->drm,
> - "Unsupported pixel format %s for 90/270!\n",
> - drm_get_format_name(fb->format->format,
> - &format_name));
> - return -EINVAL;
> - default:
> - break;
> - }
> - }
> -
> - /* Y-tiling is not supported in IF-ID Interlace mode */
> - if (crtc_state->hw.enable &&
> - crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE &&
> - (fb->modifier == I915_FORMAT_MOD_Y_TILED ||
> - fb->modifier == I915_FORMAT_MOD_Yf_TILED ||
> - fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
> - fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS ||
> - fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS ||
> - fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS ||
> - fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC)) {
> - drm_dbg_kms(&dev_priv->drm,
> - "Y/Yf tiling not supported in IF-ID mode\n");
> - return -EINVAL;
> - }
> -
> - /* Wa_1606054188:tgl,adl-s */
> - if ((IS_ALDERLAKE_S(dev_priv) || IS_TIGERLAKE(dev_priv)) &&
> - plane_state->ckey.flags & I915_SET_COLORKEY_SOURCE &&
> - intel_format_is_p01x(fb->format->format)) {
> - drm_dbg_kms(&dev_priv->drm,
> - "Source color keying not supported with P01x formats\n");
> - return -EINVAL;
> - }
> -
> - return 0;
> -}
> -
> -static int skl_plane_check_dst_coordinates(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);
> - int crtc_x = plane_state->uapi.dst.x1;
> - int crtc_w = drm_rect_width(&plane_state->uapi.dst);
> - int pipe_src_w = crtc_state->pipe_src_w;
> -
> - /*
> - * Display WA #1175: cnl,glk
> - * Planes other than the cursor may cause FIFO underflow and display
> - * corruption if starting less than 4 pixels from the right edge of
> - * the screen.
> - * Besides the above WA fix the similar problem, where planes other
> - * than the cursor ending less than 4 pixels from the left edge of the
> - * screen may cause FIFO underflow and display corruption.
> - */
> - if ((IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) &&
> - (crtc_x + crtc_w < 4 || crtc_x > pipe_src_w - 4)) {
> - drm_dbg_kms(&dev_priv->drm,
> - "requested plane X %s position %d invalid (valid range %d-%d)\n",
> - crtc_x + crtc_w < 4 ? "end" : "start",
> - crtc_x + crtc_w < 4 ? crtc_x + crtc_w : crtc_x,
> - 4, pipe_src_w - 4);
> - return -ERANGE;
> - }
> -
> - return 0;
> -}
> -
> -static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_state)
> -{
> - const struct drm_framebuffer *fb = plane_state->hw.fb;
> - unsigned int rotation = plane_state->hw.rotation;
> - int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
> -
> - /* Display WA #1106 */
> - if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
> - 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 planar YUV\n");
> - return -EINVAL;
> - }
> -
> - return 0;
> -}
> -
> -static int skl_plane_max_scale(struct drm_i915_private *dev_priv,
> - const struct drm_framebuffer *fb)
> -{
> - /*
> - * We don't yet know the final source width nor
> - * whether we can use the HQ scaler mode. Assume
> - * the best case.
> - * FIXME need to properly check this later.
> - */
> - if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv) ||
> - !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
> - return 0x30000 - 1;
> - else
> - return 0x20000 - 1;
> -}
> -
> -static int skl_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);
> - struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> - const struct drm_framebuffer *fb = plane_state->hw.fb;
> - int min_scale = DRM_PLANE_HELPER_NO_SCALING;
> - int max_scale = DRM_PLANE_HELPER_NO_SCALING;
> - int ret;
> -
> - ret = skl_plane_check_fb(crtc_state, plane_state);
> - if (ret)
> - return ret;
> -
> - /* use scaler when colorkey is not required */
> - if (!plane_state->ckey.flags && intel_fb_scalable(fb)) {
> - min_scale = 1;
> - max_scale = skl_plane_max_scale(dev_priv, fb);
> - }
> -
> - ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
> - min_scale, max_scale, true);
> - if (ret)
> - return ret;
> -
> - ret = skl_check_plane_surface(plane_state);
> - if (ret)
> - return ret;
> -
> - if (!plane_state->uapi.visible)
> - return 0;
> -
> - ret = skl_plane_check_dst_coordinates(crtc_state, plane_state);
> - if (ret)
> - return ret;
> -
> - ret = intel_plane_check_src_coordinates(plane_state);
> - if (ret)
> - return ret;
> -
> - ret = skl_plane_check_nv12_rotation(plane_state);
> - if (ret)
> - return ret;
> -
> - /* HW only has 8 bits pixel precision, disable plane if invisible */
> - if (!(plane_state->hw.alpha >> 8))
> - plane_state->uapi.visible = false;
> -
> - plane_state->ctl = skl_plane_ctl(crtc_state, plane_state);
> -
> - if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
> - plane_state->color_ctl = glk_plane_color_ctl(crtc_state,
> - plane_state);
> -
> - if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
> - icl_is_hdr_plane(dev_priv, plane->id))
> - /* Enable and use MPEG-2 chroma siting */
> - plane_state->cus_ctl = PLANE_CUS_ENABLE |
> - PLANE_CUS_HPHASE_0 |
> - PLANE_CUS_VPHASE_SIGN_NEGATIVE | PLANE_CUS_VPHASE_0_25;
> - else
> - plane_state->cus_ctl = 0;
> -
> - return 0;
> -}
> -
> -static bool has_dst_key_in_primary_plane(struct drm_i915_private *dev_priv)
> -{
> - return INTEL_GEN(dev_priv) >= 9;
> -}
> -
> -static void intel_plane_set_ckey(struct intel_plane_state *plane_state,
> - const struct drm_intel_sprite_colorkey *set)
> -{
> - struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
> - struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> - struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
> -
> - *key = *set;
> + *key = *set;
>
> /*
> * We want src key enabled on the
> @@ -2708,186 +1958,6 @@ static const u32 chv_pipe_b_sprite_formats[] = {
> DRM_FORMAT_VYUY,
> };
>
> -static const u32 skl_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_YUYV,
> - DRM_FORMAT_YVYU,
> - DRM_FORMAT_UYVY,
> - DRM_FORMAT_VYUY,
> - DRM_FORMAT_XYUV8888,
> -};
> -
> -static const u32 skl_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_YUYV,
> - DRM_FORMAT_YVYU,
> - DRM_FORMAT_UYVY,
> - DRM_FORMAT_VYUY,
> - DRM_FORMAT_NV12,
> - DRM_FORMAT_XYUV8888,
> -};
> -
> -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_XRGB16161616F,
> - DRM_FORMAT_XBGR16161616F,
> - DRM_FORMAT_YUYV,
> - DRM_FORMAT_YVYU,
> - DRM_FORMAT_UYVY,
> - DRM_FORMAT_VYUY,
> - DRM_FORMAT_NV12,
> - DRM_FORMAT_XYUV8888,
> - DRM_FORMAT_P010,
> - DRM_FORMAT_P012,
> - DRM_FORMAT_P016,
> -};
> -
> -static const u32 icl_sdr_y_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_ARGB2101010,
> - DRM_FORMAT_ABGR2101010,
> - DRM_FORMAT_YUYV,
> - DRM_FORMAT_YVYU,
> - DRM_FORMAT_UYVY,
> - DRM_FORMAT_VYUY,
> - DRM_FORMAT_Y210,
> - DRM_FORMAT_Y212,
> - DRM_FORMAT_Y216,
> - DRM_FORMAT_XYUV8888,
> - DRM_FORMAT_XVYU2101010,
> - DRM_FORMAT_XVYU12_16161616,
> - DRM_FORMAT_XVYU16161616,
> -};
> -
> -static const u32 icl_sdr_uv_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_ARGB2101010,
> - DRM_FORMAT_ABGR2101010,
> - 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_XYUV8888,
> - 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_ARGB2101010,
> - DRM_FORMAT_ABGR2101010,
> - 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_XYUV8888,
> - 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,
> - I915_FORMAT_MOD_X_TILED,
> - DRM_FORMAT_MOD_LINEAR,
> - DRM_FORMAT_MOD_INVALID
> -};
> -
> -static const u64 skl_plane_format_modifiers_ccs[] = {
> - I915_FORMAT_MOD_Yf_TILED_CCS,
> - I915_FORMAT_MOD_Y_TILED_CCS,
> - I915_FORMAT_MOD_Yf_TILED,
> - I915_FORMAT_MOD_Y_TILED,
> - I915_FORMAT_MOD_X_TILED,
> - DRM_FORMAT_MOD_LINEAR,
> - DRM_FORMAT_MOD_INVALID
> -};
> -
> -static const u64 gen12_plane_format_modifiers_mc_ccs[] = {
> - I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS,
> - I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS,
> - I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC,
> - I915_FORMAT_MOD_Y_TILED,
> - I915_FORMAT_MOD_X_TILED,
> - DRM_FORMAT_MOD_LINEAR,
> - DRM_FORMAT_MOD_INVALID
> -};
> -
> -static const u64 gen12_plane_format_modifiers_rc_ccs[] = {
> - I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS,
> - I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC,
> - I915_FORMAT_MOD_Y_TILED,
> - I915_FORMAT_MOD_X_TILED,
> - DRM_FORMAT_MOD_LINEAR,
> - DRM_FORMAT_MOD_INVALID
> -};
> -
> static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane,
> u32 format, u64 modifier)
> {
> @@ -2980,150 +2050,6 @@ static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane,
> }
> }
>
> -static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
> - u32 format, u64 modifier)
> -{
> - struct intel_plane *plane = to_intel_plane(_plane);
> -
> - switch (modifier) {
> - case DRM_FORMAT_MOD_LINEAR:
> - case I915_FORMAT_MOD_X_TILED:
> - case I915_FORMAT_MOD_Y_TILED:
> - case I915_FORMAT_MOD_Yf_TILED:
> - break;
> - case I915_FORMAT_MOD_Y_TILED_CCS:
> - case I915_FORMAT_MOD_Yf_TILED_CCS:
> - if (!plane->has_ccs)
> - return false;
> - break;
> - default:
> - return false;
> - }
> -
> - switch (format) {
> - case DRM_FORMAT_XRGB8888:
> - case DRM_FORMAT_XBGR8888:
> - case DRM_FORMAT_ARGB8888:
> - case DRM_FORMAT_ABGR8888:
> - if (is_ccs_modifier(modifier))
> - return true;
> - fallthrough;
> - case DRM_FORMAT_RGB565:
> - case DRM_FORMAT_XRGB2101010:
> - case DRM_FORMAT_XBGR2101010:
> - case DRM_FORMAT_ARGB2101010:
> - case DRM_FORMAT_ABGR2101010:
> - case DRM_FORMAT_YUYV:
> - case DRM_FORMAT_YVYU:
> - case DRM_FORMAT_UYVY:
> - case DRM_FORMAT_VYUY:
> - case DRM_FORMAT_NV12:
> - case DRM_FORMAT_XYUV8888:
> - 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;
> - fallthrough;
> - 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)
> - return true;
> - fallthrough;
> - default:
> - return false;
> - }
> -}
> -
> -static bool gen12_plane_supports_mc_ccs(struct drm_i915_private *dev_priv,
> - enum plane_id plane_id)
> -{
> - /* Wa_14010477008:tgl[a0..c0],rkl[all],dg1[all] */
> - if (IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv) ||
> - IS_TGL_DISP_STEPPING(dev_priv, STEP_A0, STEP_C0))
> - return false;
> -
> - return plane_id < PLANE_SPRITE4;
> -}
> -
> -static bool gen12_plane_format_mod_supported(struct drm_plane *_plane,
> - u32 format, u64 modifier)
> -{
> - struct drm_i915_private *dev_priv = to_i915(_plane->dev);
> - struct intel_plane *plane = to_intel_plane(_plane);
> -
> - switch (modifier) {
> - case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
> - if (!gen12_plane_supports_mc_ccs(dev_priv, plane->id))
> - return false;
> - fallthrough;
> - case DRM_FORMAT_MOD_LINEAR:
> - case I915_FORMAT_MOD_X_TILED:
> - case I915_FORMAT_MOD_Y_TILED:
> - case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
> - case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
> - break;
> - default:
> - return false;
> - }
> -
> - switch (format) {
> - case DRM_FORMAT_XRGB8888:
> - case DRM_FORMAT_XBGR8888:
> - case DRM_FORMAT_ARGB8888:
> - case DRM_FORMAT_ABGR8888:
> - if (is_ccs_modifier(modifier))
> - return true;
> - fallthrough;
> - case DRM_FORMAT_YUYV:
> - case DRM_FORMAT_YVYU:
> - case DRM_FORMAT_UYVY:
> - case DRM_FORMAT_VYUY:
> - case DRM_FORMAT_NV12:
> - case DRM_FORMAT_XYUV8888:
> - case DRM_FORMAT_P010:
> - case DRM_FORMAT_P012:
> - case DRM_FORMAT_P016:
> - if (modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS)
> - return true;
> - fallthrough;
> - case DRM_FORMAT_RGB565:
> - case DRM_FORMAT_XRGB2101010:
> - case DRM_FORMAT_XBGR2101010:
> - case DRM_FORMAT_ARGB2101010:
> - case DRM_FORMAT_ABGR2101010:
> - case DRM_FORMAT_XVYU2101010:
> - 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)
> - return true;
> - fallthrough;
> - default:
> - return false;
> - }
> -}
> -
> static const struct drm_plane_funcs g4x_sprite_funcs = {
> .update_plane = drm_atomic_helper_update_plane,
> .disable_plane = drm_atomic_helper_disable_plane,
> @@ -3151,257 +2077,6 @@ static const struct drm_plane_funcs vlv_sprite_funcs = {
> .format_mod_supported = vlv_sprite_format_mod_supported,
> };
>
> -static const struct drm_plane_funcs skl_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 = skl_plane_format_mod_supported,
> -};
> -
> -static const struct drm_plane_funcs gen12_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 = gen12_plane_format_mod_supported,
> -};
> -
> -static bool skl_plane_has_fbc(struct drm_i915_private *dev_priv,
> - enum pipe pipe, enum plane_id plane_id)
> -{
> - if (!HAS_FBC(dev_priv))
> - return false;
> -
> - return pipe == PIPE_A && plane_id == PLANE_PRIMARY;
> -}
> -
> -static bool skl_plane_has_planar(struct drm_i915_private *dev_priv,
> - enum pipe pipe, enum plane_id plane_id)
> -{
> - /* Display WA #0870: skl, bxt */
> - if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))
> - return false;
> -
> - if (IS_GEN(dev_priv, 9) && !IS_GEMINILAKE(dev_priv) && pipe == PIPE_C)
> - return false;
> -
> - if (plane_id != PLANE_PRIMARY && plane_id != PLANE_SPRITE0)
> - return false;
> -
> - return true;
> -}
> -
> -static const u32 *skl_get_plane_formats(struct drm_i915_private *dev_priv,
> - enum pipe pipe, enum plane_id plane_id,
> - int *num_formats)
> -{
> - if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
> - *num_formats = ARRAY_SIZE(skl_planar_formats);
> - return skl_planar_formats;
> - } else {
> - *num_formats = ARRAY_SIZE(skl_plane_formats);
> - return skl_plane_formats;
> - }
> -}
> -
> -static const u32 *glk_get_plane_formats(struct drm_i915_private *dev_priv,
> - enum pipe pipe, enum plane_id plane_id,
> - int *num_formats)
> -{
> - if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
> - *num_formats = ARRAY_SIZE(glk_planar_formats);
> - return glk_planar_formats;
> - } else {
> - *num_formats = ARRAY_SIZE(skl_plane_formats);
> - return skl_plane_formats;
> - }
> -}
> -
> -static const u32 *icl_get_plane_formats(struct drm_i915_private *dev_priv,
> - enum pipe pipe, enum plane_id plane_id,
> - int *num_formats)
> -{
> - if (icl_is_hdr_plane(dev_priv, plane_id)) {
> - *num_formats = ARRAY_SIZE(icl_hdr_plane_formats);
> - return icl_hdr_plane_formats;
> - } else if (icl_is_nv12_y_plane(dev_priv, plane_id)) {
> - *num_formats = ARRAY_SIZE(icl_sdr_y_plane_formats);
> - return icl_sdr_y_plane_formats;
> - } else {
> - *num_formats = ARRAY_SIZE(icl_sdr_uv_plane_formats);
> - return icl_sdr_uv_plane_formats;
> - }
> -}
> -
> -static const u64 *gen12_get_plane_modifiers(struct drm_i915_private *dev_priv,
> - enum plane_id plane_id)
> -{
> - if (gen12_plane_supports_mc_ccs(dev_priv, plane_id))
> - return gen12_plane_format_modifiers_mc_ccs;
> - else
> - return gen12_plane_format_modifiers_rc_ccs;
> -}
> -
> -static bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
> - enum pipe pipe, enum plane_id plane_id)
> -{
> - if (plane_id == PLANE_CURSOR)
> - return false;
> -
> - if (INTEL_GEN(dev_priv) >= 10)
> - return true;
> -
> - if (IS_GEMINILAKE(dev_priv))
> - return pipe != PIPE_C;
> -
> - return pipe != PIPE_C &&
> - (plane_id == PLANE_PRIMARY ||
> - plane_id == PLANE_SPRITE0);
> -}
> -
> -struct intel_plane *
> -skl_universal_plane_create(struct drm_i915_private *dev_priv,
> - enum pipe pipe, enum plane_id plane_id)
> -{
> - const struct drm_plane_funcs *plane_funcs;
> - struct intel_plane *plane;
> - enum drm_plane_type plane_type;
> - unsigned int supported_rotations;
> - unsigned int supported_csc;
> - const u64 *modifiers;
> - const u32 *formats;
> - int num_formats;
> - int ret;
> -
> - plane = intel_plane_alloc();
> - if (IS_ERR(plane))
> - return plane;
> -
> - plane->pipe = pipe;
> - plane->id = plane_id;
> - plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane_id);
> -
> - plane->has_fbc = skl_plane_has_fbc(dev_priv, pipe, plane_id);
> - if (plane->has_fbc) {
> - struct intel_fbc *fbc = &dev_priv->fbc;
> -
> - fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
> - }
> -
> - if (INTEL_GEN(dev_priv) >= 11) {
> - plane->min_width = icl_plane_min_width;
> - plane->max_width = icl_plane_max_width;
> - plane->max_height = icl_plane_max_height;
> - } else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) {
> - plane->max_width = glk_plane_max_width;
> - plane->max_height = skl_plane_max_height;
> - } else {
> - plane->max_width = skl_plane_max_width;
> - plane->max_height = skl_plane_max_height;
> - }
> -
> - plane->max_stride = skl_plane_max_stride;
> - plane->update_plane = skl_update_plane;
> - plane->disable_plane = skl_disable_plane;
> - plane->get_hw_state = skl_plane_get_hw_state;
> - plane->check_plane = skl_plane_check;
> - plane->min_cdclk = skl_plane_min_cdclk;
> -
> - if (plane_id == PLANE_PRIMARY) {
> - plane->need_async_flip_disable_wa = IS_GEN_RANGE(dev_priv, 9, 10);
> - plane->async_flip = skl_plane_async_flip;
> - plane->enable_flip_done = skl_plane_enable_flip_done;
> - plane->disable_flip_done = skl_plane_disable_flip_done;
> - }
> -
> - if (INTEL_GEN(dev_priv) >= 11)
> - formats = icl_get_plane_formats(dev_priv, pipe,
> - plane_id, &num_formats);
> - else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
> - formats = glk_get_plane_formats(dev_priv, pipe,
> - plane_id, &num_formats);
> - else
> - formats = skl_get_plane_formats(dev_priv, pipe,
> - plane_id, &num_formats);
> -
> - plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, plane_id);
> - if (INTEL_GEN(dev_priv) >= 12) {
> - modifiers = gen12_get_plane_modifiers(dev_priv, plane_id);
> - plane_funcs = &gen12_plane_funcs;
> - } else {
> - if (plane->has_ccs)
> - modifiers = skl_plane_format_modifiers_ccs;
> - else
> - modifiers = skl_plane_format_modifiers_noccs;
> - plane_funcs = &skl_plane_funcs;
> - }
> -
> - if (plane_id == PLANE_PRIMARY)
> - plane_type = DRM_PLANE_TYPE_PRIMARY;
> - else
> - plane_type = DRM_PLANE_TYPE_OVERLAY;
> -
> - ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
> - 0, plane_funcs,
> - formats, num_formats, modifiers,
> - plane_type,
> - "plane %d%c", plane_id + 1,
> - pipe_name(pipe));
> - if (ret)
> - goto fail;
> -
> - supported_rotations =
> - DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
> - DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
> -
> - if (INTEL_GEN(dev_priv) >= 10)
> - supported_rotations |= DRM_MODE_REFLECT_X;
> -
> - drm_plane_create_rotation_property(&plane->base,
> - DRM_MODE_ROTATE_0,
> - supported_rotations);
> -
> - supported_csc = BIT(DRM_COLOR_YCBCR_BT601) | BIT(DRM_COLOR_YCBCR_BT709);
> -
> - if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
> - supported_csc |= BIT(DRM_COLOR_YCBCR_BT2020);
> -
> - drm_plane_create_color_properties(&plane->base,
> - supported_csc,
> - BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
> - BIT(DRM_COLOR_YCBCR_FULL_RANGE),
> - DRM_COLOR_YCBCR_BT709,
> - DRM_COLOR_YCBCR_LIMITED_RANGE);
> -
> - drm_plane_create_alpha_property(&plane->base);
> - drm_plane_create_blend_mode_property(&plane->base,
> - BIT(DRM_MODE_BLEND_PIXEL_NONE) |
> - BIT(DRM_MODE_BLEND_PREMULTI) |
> - BIT(DRM_MODE_BLEND_COVERAGE));
> -
> - drm_plane_create_zpos_immutable_property(&plane->base, plane_id);
> -
> - if (INTEL_GEN(dev_priv) >= 12)
> - drm_plane_enable_fb_damage_clips(&plane->base);
> -
> - if (INTEL_GEN(dev_priv) >= 10)
> - drm_plane_create_scaling_filter_property(&plane->base,
> - BIT(DRM_SCALING_FILTER_DEFAULT) |
> - BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
> -
> - drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
> -
> - return plane;
> -
> -fail:
> - intel_plane_free(plane);
> -
> - return ERR_PTR(ret);
> -}
> -
> struct intel_plane *
> intel_sprite_plane_create(struct drm_i915_private *dev_priv,
> enum pipe pipe, int sprite)
> @@ -3414,10 +2089,6 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
> int num_formats;
> int ret, zpos;
>
> - if (INTEL_GEN(dev_priv) >= 9)
> - return skl_universal_plane_create(dev_priv, pipe,
> - PLANE_SPRITE0 + sprite);
> -
> plane = intel_plane_alloc();
> if (IS_ERR(plane))
> return plane;
> diff --git a/drivers/gpu/drm/i915/display/intel_sprite.h b/drivers/gpu/drm/i915/display/intel_sprite.h
> index 76126dd8d584..418897f953fc 100644
> --- a/drivers/gpu/drm/i915/display/intel_sprite.h
> +++ b/drivers/gpu/drm/i915/display/intel_sprite.h
> @@ -38,9 +38,6 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state);
> int intel_plane_check_stride(const struct intel_plane_state *plane_state);
> int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state);
> int chv_plane_check_rotation(const struct intel_plane_state *plane_state);
> -struct intel_plane *
> -skl_universal_plane_create(struct drm_i915_private *dev_priv,
> - enum pipe pipe, enum plane_id plane_id);
>
> static inline u8 icl_hdr_plane_mask(void)
> {
> @@ -59,4 +56,7 @@ int hsw_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
> int vlv_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
> const struct intel_plane_state *plane_state);
>
> +void skl_program_scaler(struct intel_plane *plane,
> + const struct intel_crtc_state *crtc_state,
> + const struct intel_plane_state *plane_state);
> #endif /* __INTEL_SPRITE_H__ */
> diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c
> new file mode 100644
> index 000000000000..29c2e3693e8b
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
> @@ -0,0 +1,2265 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2020 Intel Corporation
> + */
> +
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_damage_helper.h>
> +#include <drm/drm_fourcc.h>
> +#include <drm/drm_plane_helper.h>
> +
> +#include "i915_drv.h"
> +#include "intel_atomic_plane.h"
> +#include "intel_display_types.h"
> +#include "intel_pm.h"
> +#include "intel_psr.h"
> +#include "intel_sprite.h"
> +#include "skl_universal_plane.h"
> +
> +static const u32 skl_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_YUYV,
> + DRM_FORMAT_YVYU,
> + DRM_FORMAT_UYVY,
> + DRM_FORMAT_VYUY,
> + DRM_FORMAT_XYUV8888,
> +};
> +
> +static const u32 skl_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_YUYV,
> + DRM_FORMAT_YVYU,
> + DRM_FORMAT_UYVY,
> + DRM_FORMAT_VYUY,
> + DRM_FORMAT_NV12,
> + DRM_FORMAT_XYUV8888,
> +};
> +
> +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_XRGB16161616F,
> + DRM_FORMAT_XBGR16161616F,
> + DRM_FORMAT_YUYV,
> + DRM_FORMAT_YVYU,
> + DRM_FORMAT_UYVY,
> + DRM_FORMAT_VYUY,
> + DRM_FORMAT_NV12,
> + DRM_FORMAT_XYUV8888,
> + DRM_FORMAT_P010,
> + DRM_FORMAT_P012,
> + DRM_FORMAT_P016,
> +};
> +
> +static const u32 icl_sdr_y_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_ARGB2101010,
> + DRM_FORMAT_ABGR2101010,
> + DRM_FORMAT_YUYV,
> + DRM_FORMAT_YVYU,
> + DRM_FORMAT_UYVY,
> + DRM_FORMAT_VYUY,
> + DRM_FORMAT_Y210,
> + DRM_FORMAT_Y212,
> + DRM_FORMAT_Y216,
> + DRM_FORMAT_XYUV8888,
> + DRM_FORMAT_XVYU2101010,
> + DRM_FORMAT_XVYU12_16161616,
> + DRM_FORMAT_XVYU16161616,
> +};
> +
> +static const u32 icl_sdr_uv_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_ARGB2101010,
> + DRM_FORMAT_ABGR2101010,
> + 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_XYUV8888,
> + 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_ARGB2101010,
> + DRM_FORMAT_ABGR2101010,
> + 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_XYUV8888,
> + 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,
> + I915_FORMAT_MOD_X_TILED,
> + DRM_FORMAT_MOD_LINEAR,
> + DRM_FORMAT_MOD_INVALID
> +};
> +
> +static const u64 skl_plane_format_modifiers_ccs[] = {
> + I915_FORMAT_MOD_Yf_TILED_CCS,
> + I915_FORMAT_MOD_Y_TILED_CCS,
> + I915_FORMAT_MOD_Yf_TILED,
> + I915_FORMAT_MOD_Y_TILED,
> + I915_FORMAT_MOD_X_TILED,
> + DRM_FORMAT_MOD_LINEAR,
> + DRM_FORMAT_MOD_INVALID
> +};
> +
> +static const u64 gen12_plane_format_modifiers_mc_ccs[] = {
> + I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS,
> + I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS,
> + I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC,
> + I915_FORMAT_MOD_Y_TILED,
> + I915_FORMAT_MOD_X_TILED,
> + DRM_FORMAT_MOD_LINEAR,
> + DRM_FORMAT_MOD_INVALID
> +};
> +
> +static const u64 gen12_plane_format_modifiers_rc_ccs[] = {
> + I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS,
> + I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC,
> + I915_FORMAT_MOD_Y_TILED,
> + I915_FORMAT_MOD_X_TILED,
> + DRM_FORMAT_MOD_LINEAR,
> + DRM_FORMAT_MOD_INVALID
> +};
> +
> +int skl_format_to_fourcc(int format, bool rgb_order, bool alpha)
> +{
> + switch (format) {
> + case PLANE_CTL_FORMAT_RGB_565:
> + return DRM_FORMAT_RGB565;
> + case PLANE_CTL_FORMAT_NV12:
> + return DRM_FORMAT_NV12;
> + case PLANE_CTL_FORMAT_XYUV:
> + return DRM_FORMAT_XYUV8888;
> + case PLANE_CTL_FORMAT_P010:
> + return DRM_FORMAT_P010;
> + case PLANE_CTL_FORMAT_P012:
> + return DRM_FORMAT_P012;
> + case PLANE_CTL_FORMAT_P016:
> + return DRM_FORMAT_P016;
> + case PLANE_CTL_FORMAT_Y210:
> + return DRM_FORMAT_Y210;
> + case PLANE_CTL_FORMAT_Y212:
> + return DRM_FORMAT_Y212;
> + case PLANE_CTL_FORMAT_Y216:
> + return DRM_FORMAT_Y216;
> + case PLANE_CTL_FORMAT_Y410:
> + return DRM_FORMAT_XVYU2101010;
> + case PLANE_CTL_FORMAT_Y412:
> + return DRM_FORMAT_XVYU12_16161616;
> + case PLANE_CTL_FORMAT_Y416:
> + return DRM_FORMAT_XVYU16161616;
> + default:
> + case PLANE_CTL_FORMAT_XRGB_8888:
> + if (rgb_order) {
> + if (alpha)
> + return DRM_FORMAT_ABGR8888;
> + else
> + return DRM_FORMAT_XBGR8888;
> + } else {
> + if (alpha)
> + return DRM_FORMAT_ARGB8888;
> + else
> + return DRM_FORMAT_XRGB8888;
> + }
> + case PLANE_CTL_FORMAT_XRGB_2101010:
> + if (rgb_order) {
> + if (alpha)
> + return DRM_FORMAT_ABGR2101010;
> + else
> + return DRM_FORMAT_XBGR2101010;
> + } else {
> + if (alpha)
> + return DRM_FORMAT_ARGB2101010;
> + else
> + return DRM_FORMAT_XRGB2101010;
> + }
> + case PLANE_CTL_FORMAT_XRGB_16161616F:
> + if (rgb_order) {
> + if (alpha)
> + return DRM_FORMAT_ABGR16161616F;
> + else
> + return DRM_FORMAT_XBGR16161616F;
> + } else {
> + if (alpha)
> + return DRM_FORMAT_ARGB16161616F;
> + else
> + return DRM_FORMAT_XRGB16161616F;
> + }
> + }
> +}
> +
> +static u8 icl_nv12_y_plane_mask(struct drm_i915_private *i915)
> +{
> + if (HAS_D12_PLANE_MINIMIZATION(i915))
> + return BIT(PLANE_SPRITE2) | BIT(PLANE_SPRITE3);
> + else
> + return BIT(PLANE_SPRITE4) | BIT(PLANE_SPRITE5);
> +}
> +
> +bool icl_is_nv12_y_plane(struct drm_i915_private *dev_priv,
> + enum plane_id plane_id)
> +{
> + return INTEL_GEN(dev_priv) >= 11 &&
> + icl_nv12_y_plane_mask(dev_priv) & BIT(plane_id);
> +}
> +
> +bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id)
> +{
> + return INTEL_GEN(dev_priv) >= 11 &&
> + icl_hdr_plane_mask() & BIT(plane_id);
> +}
> +
> +static void
> +skl_plane_ratio(const struct intel_crtc_state *crtc_state,
> + const struct intel_plane_state *plane_state,
> + unsigned int *num, unsigned int *den)
> +{
> + struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev);
> + const struct drm_framebuffer *fb = plane_state->hw.fb;
> +
> + if (fb->format->cpp[0] == 8) {
> + if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) {
> + *num = 10;
> + *den = 8;
> + } else {
> + *num = 9;
> + *den = 8;
> + }
> + } else {
> + *num = 1;
> + *den = 1;
> + }
> +}
> +
> +static int skl_plane_min_cdclk(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);
> + unsigned int num, den;
> + unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
> +
> + skl_plane_ratio(crtc_state, plane_state, &num, &den);
> +
> + /* two pixels per clock on glk+ */
> + if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
> + den *= 2;
> +
> + return DIV_ROUND_UP(pixel_rate * num, den);
> +}
> +
> +static int skl_plane_max_width(const struct drm_framebuffer *fb,
> + int color_plane,
> + unsigned int rotation)
> +{
> + int cpp = fb->format->cpp[color_plane];
> +
> + switch (fb->modifier) {
> + case DRM_FORMAT_MOD_LINEAR:
> + case I915_FORMAT_MOD_X_TILED:
> + /*
> + * Validated limit is 4k, but has 5k should
> + * work apart from the following features:
> + * - Ytile (already limited to 4k)
> + * - FP16 (already limited to 4k)
> + * - render compression (already limited to 4k)
> + * - KVMR sprite and cursor (don't care)
> + * - horizontal panning (TODO verify this)
> + * - pipe and plane scaling (TODO verify this)
> + */
> + if (cpp == 8)
> + return 4096;
> + else
> + return 5120;
> + case I915_FORMAT_MOD_Y_TILED_CCS:
> + case I915_FORMAT_MOD_Yf_TILED_CCS:
> + case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
> + /* FIXME AUX plane? */
> + case I915_FORMAT_MOD_Y_TILED:
> + case I915_FORMAT_MOD_Yf_TILED:
> + if (cpp == 8)
> + return 2048;
> + else
> + return 4096;
> + default:
> + MISSING_CASE(fb->modifier);
> + return 2048;
> + }
> +}
> +
> +static int glk_plane_max_width(const struct drm_framebuffer *fb,
> + int color_plane,
> + unsigned int rotation)
> +{
> + int cpp = fb->format->cpp[color_plane];
> +
> + switch (fb->modifier) {
> + case DRM_FORMAT_MOD_LINEAR:
> + case I915_FORMAT_MOD_X_TILED:
> + if (cpp == 8)
> + return 4096;
> + else
> + return 5120;
> + case I915_FORMAT_MOD_Y_TILED_CCS:
> + case I915_FORMAT_MOD_Yf_TILED_CCS:
> + /* FIXME AUX plane? */
> + case I915_FORMAT_MOD_Y_TILED:
> + case I915_FORMAT_MOD_Yf_TILED:
> + if (cpp == 8)
> + return 2048;
> + else
> + return 5120;
> + default:
> + MISSING_CASE(fb->modifier);
> + return 2048;
> + }
> +}
> +
> +static int icl_plane_min_width(const struct drm_framebuffer *fb,
> + int color_plane,
> + unsigned int rotation)
> +{
> + /* Wa_14011264657, Wa_14011050563: gen11+ */
> + switch (fb->format->format) {
> + case DRM_FORMAT_C8:
> + return 18;
> + case DRM_FORMAT_RGB565:
> + return 10;
> + 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_XVYU2101010:
> + case DRM_FORMAT_Y212:
> + case DRM_FORMAT_Y216:
> + return 6;
> + case DRM_FORMAT_NV12:
> + return 20;
> + case DRM_FORMAT_P010:
> + case DRM_FORMAT_P012:
> + case DRM_FORMAT_P016:
> + return 12;
> + case DRM_FORMAT_XRGB16161616F:
> + case DRM_FORMAT_XBGR16161616F:
> + case DRM_FORMAT_ARGB16161616F:
> + case DRM_FORMAT_ABGR16161616F:
> + case DRM_FORMAT_XVYU12_16161616:
> + case DRM_FORMAT_XVYU16161616:
> + return 4;
> + default:
> + return 1;
> + }
> +}
> +
> +static int icl_plane_max_width(const struct drm_framebuffer *fb,
> + int color_plane,
> + unsigned int rotation)
> +{
> + return 5120;
> +}
> +
> +static int skl_plane_max_height(const struct drm_framebuffer *fb,
> + int color_plane,
> + unsigned int rotation)
> +{
> + return 4096;
> +}
> +
> +static int icl_plane_max_height(const struct drm_framebuffer *fb,
> + int color_plane,
> + unsigned int rotation)
> +{
> + return 4320;
> +}
> +
> +static unsigned int
> +skl_plane_max_stride(struct intel_plane *plane,
> + u32 pixel_format, u64 modifier,
> + unsigned int rotation)
> +{
> + const struct drm_format_info *info = drm_format_info(pixel_format);
> + int cpp = info->cpp[0];
> +
> + /*
> + * "The stride in bytes must not exceed the
> + * of the size of 8K pixels and 32K bytes."
> + */
> + if (drm_rotation_90_or_270(rotation))
> + return min(8192, 32768 / cpp);
> + else
> + return min(8192 * cpp, 32768);
> +}
> +
> +
> +/* Preoffset values for YUV to RGB Conversion */
> +#define PREOFF_YUV_TO_RGB_HI 0x1800
> +#define PREOFF_YUV_TO_RGB_ME 0x0000
> +#define PREOFF_YUV_TO_RGB_LO 0x1800
> +
> +#define ROFF(x) (((x) & 0xffff) << 16)
> +#define GOFF(x) (((x) & 0xffff) << 0)
> +#define BOFF(x) (((x) & 0xffff) << 16)
> +
> +/*
> + * Programs the input color space conversion stage for ICL HDR planes.
> + * Note that it is assumed that this stage always happens after YUV
> + * range correction. Thus, the input to this stage is assumed to be
> + * in full-range YCbCr.
> + */
> +static void
> +icl_program_input_csc(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 pipe pipe = plane->pipe;
> + enum plane_id plane_id = plane->id;
> +
> + static const u16 input_csc_matrix[][9] = {
> + /*
> + * BT.601 full range YCbCr -> full range RGB
> + * The matrix required is :
> + * [1.000, 0.000, 1.371,
> + * 1.000, -0.336, -0.698,
> + * 1.000, 1.732, 0.0000]
> + */
> + [DRM_COLOR_YCBCR_BT601] = {
> + 0x7AF8, 0x7800, 0x0,
> + 0x8B28, 0x7800, 0x9AC0,
> + 0x0, 0x7800, 0x7DD8,
> + },
> + /*
> + * BT.709 full range YCbCr -> full range RGB
> + * The matrix required is :
> + * [1.000, 0.000, 1.574,
> + * 1.000, -0.187, -0.468,
> + * 1.000, 1.855, 0.0000]
> + */
> + [DRM_COLOR_YCBCR_BT709] = {
> + 0x7C98, 0x7800, 0x0,
> + 0x9EF8, 0x7800, 0xAC00,
> + 0x0, 0x7800, 0x7ED8,
> + },
> + /*
> + * BT.2020 full range YCbCr -> full range RGB
> + * The matrix required is :
> + * [1.000, 0.000, 1.474,
> + * 1.000, -0.1645, -0.5713,
> + * 1.000, 1.8814, 0.0000]
> + */
> + [DRM_COLOR_YCBCR_BT2020] = {
> + 0x7BC8, 0x7800, 0x0,
> + 0x8928, 0x7800, 0xAA88,
> + 0x0, 0x7800, 0x7F10,
> + },
> + };
> + const u16 *csc = input_csc_matrix[plane_state->hw.color_encoding];
> +
> + intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 0),
> + ROFF(csc[0]) | GOFF(csc[1]));
> + intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 1),
> + BOFF(csc[2]));
> + intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 2),
> + ROFF(csc[3]) | GOFF(csc[4]));
> + intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 3),
> + BOFF(csc[5]));
> + intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 4),
> + ROFF(csc[6]) | GOFF(csc[7]));
> + intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 5),
> + BOFF(csc[8]));
> +
> + intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 0),
> + PREOFF_YUV_TO_RGB_HI);
> + intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1),
> + PREOFF_YUV_TO_RGB_ME);
> + intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 2),
> + PREOFF_YUV_TO_RGB_LO);
> + intel_de_write_fw(dev_priv,
> + PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 0), 0x0);
> + intel_de_write_fw(dev_priv,
> + PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 1), 0x0);
> + intel_de_write_fw(dev_priv,
> + PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 2), 0x0);
> +}
> +
> +static bool is_surface_linear(const struct drm_framebuffer *fb, int color_plane)
> +{
> + return fb->modifier == DRM_FORMAT_MOD_LINEAR ||
> + is_gen12_ccs_plane(fb, color_plane);
> +}
> +
> +static unsigned int skl_plane_stride_mult(const struct drm_framebuffer *fb,
> + int color_plane, unsigned int rotation)
> +{
> + /*
> + * The stride is either expressed as a multiple of 64 bytes chunks for
> + * linear buffers or in number of tiles for tiled buffers.
> + */
> + if (is_surface_linear(fb, color_plane))
> + return 64;
> + else if (drm_rotation_90_or_270(rotation))
> + return intel_tile_height(fb, color_plane);
> + else
> + return intel_tile_width_bytes(fb, color_plane);
> +}
> +
> +static u32 skl_plane_stride(const struct intel_plane_state *plane_state,
> + int color_plane)
> +{
> + const struct drm_framebuffer *fb = plane_state->hw.fb;
> + unsigned int rotation = plane_state->hw.rotation;
> + u32 stride = plane_state->color_plane[color_plane].stride;
> +
> + if (color_plane >= fb->format->num_planes)
> + return 0;
> +
> + return stride / skl_plane_stride_mult(fb, color_plane, rotation);
> +}
> +
> +static void
> +skl_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 plane_id plane_id = plane->id;
> + enum pipe pipe = plane->pipe;
> + unsigned long irqflags;
> +
> + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
> +
> + if (icl_is_hdr_plane(dev_priv, plane_id))
> + intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id), 0);
> +
> + skl_write_plane_wm(plane, crtc_state);
> +
> + intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), 0);
> + intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), 0);
> +
> + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
> +}
> +
> +static bool
> +skl_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 plane_id plane_id = plane->id;
> + intel_wakeref_t wakeref;
> + bool ret;
> +
> + power_domain = POWER_DOMAIN_PIPE(plane->pipe);
> + wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> + if (!wakeref)
> + return false;
> +
> + ret = intel_de_read(dev_priv, PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;
> +
> + *pipe = plane->pipe;
> +
> + intel_display_power_put(dev_priv, power_domain, wakeref);
> +
> + return ret;
> +}
> +
> +static u32 skl_plane_ctl_format(u32 pixel_format)
> +{
> + switch (pixel_format) {
> + case DRM_FORMAT_C8:
> + return PLANE_CTL_FORMAT_INDEXED;
> + case DRM_FORMAT_RGB565:
> + return PLANE_CTL_FORMAT_RGB_565;
> + case DRM_FORMAT_XBGR8888:
> + case DRM_FORMAT_ABGR8888:
> + return PLANE_CTL_FORMAT_XRGB_8888 | PLANE_CTL_ORDER_RGBX;
> + case DRM_FORMAT_XRGB8888:
> + case DRM_FORMAT_ARGB8888:
> + return PLANE_CTL_FORMAT_XRGB_8888;
> + case DRM_FORMAT_XBGR2101010:
> + case DRM_FORMAT_ABGR2101010:
> + return PLANE_CTL_FORMAT_XRGB_2101010 | PLANE_CTL_ORDER_RGBX;
> + case DRM_FORMAT_XRGB2101010:
> + case DRM_FORMAT_ARGB2101010:
> + return PLANE_CTL_FORMAT_XRGB_2101010;
> + case DRM_FORMAT_XBGR16161616F:
> + case DRM_FORMAT_ABGR16161616F:
> + return PLANE_CTL_FORMAT_XRGB_16161616F | PLANE_CTL_ORDER_RGBX;
> + case DRM_FORMAT_XRGB16161616F:
> + case DRM_FORMAT_ARGB16161616F:
> + return PLANE_CTL_FORMAT_XRGB_16161616F;
> + case DRM_FORMAT_XYUV8888:
> + return PLANE_CTL_FORMAT_XYUV;
> + case DRM_FORMAT_YUYV:
> + return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_YUYV;
> + case DRM_FORMAT_YVYU:
> + return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_YVYU;
> + case DRM_FORMAT_UYVY:
> + return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_UYVY;
> + case DRM_FORMAT_VYUY:
> + return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_VYUY;
> + case DRM_FORMAT_NV12:
> + return PLANE_CTL_FORMAT_NV12;
> + case DRM_FORMAT_P010:
> + return PLANE_CTL_FORMAT_P010;
> + case DRM_FORMAT_P012:
> + return PLANE_CTL_FORMAT_P012;
> + case DRM_FORMAT_P016:
> + return PLANE_CTL_FORMAT_P016;
> + case DRM_FORMAT_Y210:
> + return PLANE_CTL_FORMAT_Y210;
> + case DRM_FORMAT_Y212:
> + return PLANE_CTL_FORMAT_Y212;
> + case DRM_FORMAT_Y216:
> + return PLANE_CTL_FORMAT_Y216;
> + case DRM_FORMAT_XVYU2101010:
> + return PLANE_CTL_FORMAT_Y410;
> + case DRM_FORMAT_XVYU12_16161616:
> + return PLANE_CTL_FORMAT_Y412;
> + case DRM_FORMAT_XVYU16161616:
> + return PLANE_CTL_FORMAT_Y416;
> + default:
> + MISSING_CASE(pixel_format);
> + }
> +
> + return 0;
> +}
> +
> +static u32 skl_plane_ctl_alpha(const struct intel_plane_state *plane_state)
> +{
> + if (!plane_state->hw.fb->format->has_alpha)
> + return PLANE_CTL_ALPHA_DISABLE;
> +
> + switch (plane_state->hw.pixel_blend_mode) {
> + case DRM_MODE_BLEND_PIXEL_NONE:
> + return PLANE_CTL_ALPHA_DISABLE;
> + case DRM_MODE_BLEND_PREMULTI:
> + return PLANE_CTL_ALPHA_SW_PREMULTIPLY;
> + case DRM_MODE_BLEND_COVERAGE:
> + return PLANE_CTL_ALPHA_HW_PREMULTIPLY;
> + default:
> + MISSING_CASE(plane_state->hw.pixel_blend_mode);
> + return PLANE_CTL_ALPHA_DISABLE;
> + }
> +}
> +
> +static u32 glk_plane_color_ctl_alpha(const struct intel_plane_state *plane_state)
> +{
> + if (!plane_state->hw.fb->format->has_alpha)
> + return PLANE_COLOR_ALPHA_DISABLE;
> +
> + switch (plane_state->hw.pixel_blend_mode) {
> + case DRM_MODE_BLEND_PIXEL_NONE:
> + return PLANE_COLOR_ALPHA_DISABLE;
> + case DRM_MODE_BLEND_PREMULTI:
> + return PLANE_COLOR_ALPHA_SW_PREMULTIPLY;
> + case DRM_MODE_BLEND_COVERAGE:
> + return PLANE_COLOR_ALPHA_HW_PREMULTIPLY;
> + default:
> + MISSING_CASE(plane_state->hw.pixel_blend_mode);
> + return PLANE_COLOR_ALPHA_DISABLE;
> + }
> +}
> +
> +static u32 skl_plane_ctl_tiling(u64 fb_modifier)
> +{
> + switch (fb_modifier) {
> + case DRM_FORMAT_MOD_LINEAR:
> + break;
> + case I915_FORMAT_MOD_X_TILED:
> + return PLANE_CTL_TILED_X;
> + case I915_FORMAT_MOD_Y_TILED:
> + return PLANE_CTL_TILED_Y;
> + case I915_FORMAT_MOD_Y_TILED_CCS:
> + case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
> + return PLANE_CTL_TILED_Y | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
> + case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
> + return PLANE_CTL_TILED_Y |
> + PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
> + PLANE_CTL_CLEAR_COLOR_DISABLE;
> + case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
> + return PLANE_CTL_TILED_Y | PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE;
> + case I915_FORMAT_MOD_Yf_TILED:
> + return PLANE_CTL_TILED_YF;
> + case I915_FORMAT_MOD_Yf_TILED_CCS:
> + return PLANE_CTL_TILED_YF | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
> + default:
> + MISSING_CASE(fb_modifier);
> + }
> +
> + return 0;
> +}
> +
> +static u32 skl_plane_ctl_rotate(unsigned int rotate)
> +{
> + switch (rotate) {
> + case DRM_MODE_ROTATE_0:
> + break;
> + /*
> + * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr
> + * while i915 HW rotation is clockwise, thats why this swapping.
> + */
> + case DRM_MODE_ROTATE_90:
> + return PLANE_CTL_ROTATE_270;
> + case DRM_MODE_ROTATE_180:
> + return PLANE_CTL_ROTATE_180;
> + case DRM_MODE_ROTATE_270:
> + return PLANE_CTL_ROTATE_90;
> + default:
> + MISSING_CASE(rotate);
> + }
> +
> + return 0;
> +}
> +
> +static u32 cnl_plane_ctl_flip(unsigned int reflect)
> +{
> + switch (reflect) {
> + case 0:
> + break;
> + case DRM_MODE_REFLECT_X:
> + return PLANE_CTL_FLIP_HORIZONTAL;
> + case DRM_MODE_REFLECT_Y:
> + default:
> + MISSING_CASE(reflect);
> + }
> +
> + return 0;
> +}
> +
> +static u32 skl_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
> +{
> + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
> + u32 plane_ctl = 0;
> +
> + if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
> + return plane_ctl;
> +
> + if (crtc_state->gamma_enable)
> + plane_ctl |= PLANE_CTL_PIPE_GAMMA_ENABLE;
> +
> + if (crtc_state->csc_enable)
> + plane_ctl |= PLANE_CTL_PIPE_CSC_ENABLE;
> +
> + return plane_ctl;
> +}
> +
> +static u32 skl_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;
> + const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
> + u32 plane_ctl;
> +
> + plane_ctl = PLANE_CTL_ENABLE;
> +
> + if (INTEL_GEN(dev_priv) < 10 && !IS_GEMINILAKE(dev_priv)) {
> + plane_ctl |= skl_plane_ctl_alpha(plane_state);
> + plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE;
> +
> + if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
> + plane_ctl |= PLANE_CTL_YUV_TO_RGB_CSC_FORMAT_BT709;
> +
> + if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
> + plane_ctl |= PLANE_CTL_YUV_RANGE_CORRECTION_DISABLE;
> + }
> +
> + plane_ctl |= skl_plane_ctl_format(fb->format->format);
> + plane_ctl |= skl_plane_ctl_tiling(fb->modifier);
> + plane_ctl |= skl_plane_ctl_rotate(rotation & DRM_MODE_ROTATE_MASK);
> +
> + if (INTEL_GEN(dev_priv) >= 10)
> + plane_ctl |= cnl_plane_ctl_flip(rotation &
> + DRM_MODE_REFLECT_MASK);
> +
> + if (key->flags & I915_SET_COLORKEY_DESTINATION)
> + plane_ctl |= PLANE_CTL_KEY_ENABLE_DESTINATION;
> + else if (key->flags & I915_SET_COLORKEY_SOURCE)
> + plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE;
> +
> + return plane_ctl;
> +}
> +
> +static u32 glk_plane_color_ctl_crtc(const struct intel_crtc_state *crtc_state)
> +{
> + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
> + u32 plane_color_ctl = 0;
> +
> + if (INTEL_GEN(dev_priv) >= 11)
> + return plane_color_ctl;
> +
> + if (crtc_state->gamma_enable)
> + plane_color_ctl |= PLANE_COLOR_PIPE_GAMMA_ENABLE;
> +
> + if (crtc_state->csc_enable)
> + plane_color_ctl |= PLANE_COLOR_PIPE_CSC_ENABLE;
> +
> + return plane_color_ctl;
> +}
> +
> +static u32 glk_plane_color_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;
> + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
> + u32 plane_color_ctl = 0;
> +
> + plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE;
> + plane_color_ctl |= glk_plane_color_ctl_alpha(plane_state);
> +
> + if (fb->format->is_yuv && !icl_is_hdr_plane(dev_priv, plane->id)) {
> + switch (plane_state->hw.color_encoding) {
> + case DRM_COLOR_YCBCR_BT709:
> + plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709;
> + break;
> + case DRM_COLOR_YCBCR_BT2020:
> + plane_color_ctl |=
> + PLANE_COLOR_CSC_MODE_YUV2020_TO_RGB2020;
> + break;
> + default:
> + plane_color_ctl |=
> + PLANE_COLOR_CSC_MODE_YUV601_TO_RGB601;
> + }
> + if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
> + plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE;
> + } else if (fb->format->is_yuv) {
> + plane_color_ctl |= PLANE_COLOR_INPUT_CSC_ENABLE;
> + if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
> + plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE;
> + }
> +
> + return plane_color_ctl;
> +}
> +
> +static int
> +main_to_ccs_plane(const struct drm_framebuffer *fb, int main_plane)
> +{
> + drm_WARN_ON(fb->dev, !is_ccs_modifier(fb->modifier) ||
> + (main_plane && main_plane >= fb->format->num_planes / 2));
> +
> + return fb->format->num_planes / 2 + main_plane;
> +}
> +
> +int skl_ccs_to_main_plane(const struct drm_framebuffer *fb, int ccs_plane)
> +{
> + drm_WARN_ON(fb->dev, !is_ccs_modifier(fb->modifier) ||
> + ccs_plane < fb->format->num_planes / 2);
> +
> + if (is_gen12_ccs_cc_plane(fb, ccs_plane))
> + return 0;
> +
> + return ccs_plane - fb->format->num_planes / 2;
> +}
> +
> +static int
> +skl_main_to_aux_plane(const struct drm_framebuffer *fb, int main_plane)
> +{
> + struct drm_i915_private *i915 = to_i915(fb->dev);
> +
> + if (is_ccs_modifier(fb->modifier))
> + return main_to_ccs_plane(fb, main_plane);
> + else if (INTEL_GEN(i915) < 11 &&
> + intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
> + return 1;
> + else
> + return 0;
> +}
> +
> +static void
> +skl_program_plane(struct intel_plane *plane,
> + const struct intel_crtc_state *crtc_state,
> + const struct intel_plane_state *plane_state,
> + int color_plane)
> +{
> + struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> + enum plane_id plane_id = plane->id;
> + enum pipe pipe = plane->pipe;
> + const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
> + u32 surf_addr = plane_state->color_plane[color_plane].offset;
> + u32 stride = skl_plane_stride(plane_state, color_plane);
> + const struct drm_framebuffer *fb = plane_state->hw.fb;
> + int aux_plane = skl_main_to_aux_plane(fb, color_plane);
> + int crtc_x = plane_state->uapi.dst.x1;
> + int crtc_y = plane_state->uapi.dst.y1;
> + u32 x = plane_state->color_plane[color_plane].x;
> + u32 y = plane_state->color_plane[color_plane].y;
> + u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
> + u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
> + u8 alpha = plane_state->hw.alpha >> 8;
> + u32 plane_color_ctl = 0, aux_dist = 0;
> + unsigned long irqflags;
> + u32 keymsk, keymax;
> + u32 plane_ctl = plane_state->ctl;
> +
> + plane_ctl |= skl_plane_ctl_crtc(crtc_state);
> +
> + if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
> + plane_color_ctl = plane_state->color_ctl |
> + glk_plane_color_ctl_crtc(crtc_state);
> +
> + /* Sizes are 0 based */
> + src_w--;
> + src_h--;
> +
> + keymax = (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha);
> +
> + keymsk = key->channel_mask & 0x7ffffff;
> + if (alpha < 0xff)
> + keymsk |= PLANE_KEYMSK_ALPHA_ENABLE;
> +
> + /* The scaler will handle the output position */
> + if (plane_state->scaler_id >= 0) {
> + crtc_x = 0;
> + crtc_y = 0;
> + }
> +
> + if (aux_plane) {
> + aux_dist = plane_state->color_plane[aux_plane].offset - surf_addr;
> +
> + if (INTEL_GEN(dev_priv) < 12)
> + aux_dist |= skl_plane_stride(plane_state, aux_plane);
> + }
> +
> + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
> +
> + intel_de_write_fw(dev_priv, PLANE_STRIDE(pipe, plane_id), stride);
> + intel_de_write_fw(dev_priv, PLANE_POS(pipe, plane_id),
> + (crtc_y << 16) | crtc_x);
> + intel_de_write_fw(dev_priv, PLANE_SIZE(pipe, plane_id),
> + (src_h << 16) | src_w);
> +
> + intel_de_write_fw(dev_priv, PLANE_AUX_DIST(pipe, plane_id), aux_dist);
> +
> + if (icl_is_hdr_plane(dev_priv, plane_id))
> + intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id),
> + plane_state->cus_ctl);
> +
> + if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
> + intel_de_write_fw(dev_priv, PLANE_COLOR_CTL(pipe, plane_id),
> + plane_color_ctl);
> +
> + if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id))
> + icl_program_input_csc(plane, crtc_state, plane_state);
> +
> + if (fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC)
> + intel_uncore_write64_fw(&dev_priv->uncore,
> + PLANE_CC_VAL(pipe, plane_id), plane_state->ccval);
> +
> + skl_write_plane_wm(plane, crtc_state);
> +
> + intel_de_write_fw(dev_priv, PLANE_KEYVAL(pipe, plane_id),
> + key->min_value);
> + intel_de_write_fw(dev_priv, PLANE_KEYMSK(pipe, plane_id), keymsk);
> + intel_de_write_fw(dev_priv, PLANE_KEYMAX(pipe, plane_id), keymax);
> +
> + intel_de_write_fw(dev_priv, PLANE_OFFSET(pipe, plane_id),
> + (y << 16) | x);
> +
> + if (INTEL_GEN(dev_priv) < 11)
> + intel_de_write_fw(dev_priv, PLANE_AUX_OFFSET(pipe, plane_id),
> + (plane_state->color_plane[1].y << 16) | plane_state->color_plane[1].x);
> +
> + if (!drm_atomic_crtc_needs_modeset(&crtc_state->uapi))
> + intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, color_plane);
> +
> + /*
> + * 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, PLANE_CTL(pipe, plane_id), plane_ctl);
> + intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
> + intel_plane_ggtt_offset(plane_state) + surf_addr);
> +
> + if (plane_state->scaler_id >= 0)
> + skl_program_scaler(plane, crtc_state, plane_state);
> +
> + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
> +}
> +
> +static void
> +skl_plane_async_flip(struct intel_plane *plane,
> + const struct intel_crtc_state *crtc_state,
> + const struct intel_plane_state *plane_state,
> + bool async_flip)
> +{
> + struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> + unsigned long irqflags;
> + enum plane_id plane_id = plane->id;
> + enum pipe pipe = plane->pipe;
> + u32 surf_addr = plane_state->color_plane[0].offset;
> + u32 plane_ctl = plane_state->ctl;
> +
> + plane_ctl |= skl_plane_ctl_crtc(crtc_state);
> +
> + if (async_flip)
> + plane_ctl |= PLANE_CTL_ASYNC_FLIP;
> +
> + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
> +
> + intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
> + intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
> + intel_plane_ggtt_offset(plane_state) + surf_addr);
> +
> + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
> +}
> +
> +static void
> +skl_update_plane(struct intel_plane *plane,
> + const struct intel_crtc_state *crtc_state,
> + const struct intel_plane_state *plane_state)
> +{
> + int color_plane = 0;
> +
> + if (plane_state->planar_linked_plane && !plane_state->planar_slave)
> + /* Program the UV plane on planar master */
> + color_plane = 1;
> +
> + skl_program_plane(plane, crtc_state, plane_state, color_plane);
> +}
> +
> +static bool intel_format_is_p01x(u32 format)
> +{
> + switch (format) {
> + case DRM_FORMAT_P010:
> + case DRM_FORMAT_P012:
> + case DRM_FORMAT_P016:
> + return true;
> + default:
> + return false;
> + }
> +}
> +
> +static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
> + const struct intel_plane_state *plane_state)
> +{
> + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
> + struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> + const struct drm_framebuffer *fb = plane_state->hw.fb;
> + unsigned int rotation = plane_state->hw.rotation;
> + struct drm_format_name_buf format_name;
> +
> + if (!fb)
> + return 0;
> +
> + if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) &&
> + is_ccs_modifier(fb->modifier)) {
> + drm_dbg_kms(&dev_priv->drm,
> + "RC support only with 0/180 degree rotation (%x)\n",
> + rotation);
> + return -EINVAL;
> + }
> +
> + if (rotation & DRM_MODE_REFLECT_X &&
> + fb->modifier == DRM_FORMAT_MOD_LINEAR) {
> + drm_dbg_kms(&dev_priv->drm,
> + "horizontal flip is not supported with linear surface formats\n");
> + return -EINVAL;
> + }
> +
> + if (drm_rotation_90_or_270(rotation)) {
> + if (fb->modifier != I915_FORMAT_MOD_Y_TILED &&
> + fb->modifier != I915_FORMAT_MOD_Yf_TILED) {
> + drm_dbg_kms(&dev_priv->drm,
> + "Y/Yf tiling required for 90/270!\n");
> + return -EINVAL;
> + }
> +
> + /*
> + * 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.
> + */
> + switch (fb->format->format) {
> + case DRM_FORMAT_RGB565:
> + if (INTEL_GEN(dev_priv) >= 11)
> + break;
> + fallthrough;
> + 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_dbg_kms(&dev_priv->drm,
> + "Unsupported pixel format %s for 90/270!\n",
> + drm_get_format_name(fb->format->format,
> + &format_name));
> + return -EINVAL;
> + default:
> + break;
> + }
> + }
> +
> + /* Y-tiling is not supported in IF-ID Interlace mode */
> + if (crtc_state->hw.enable &&
> + crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE &&
> + (fb->modifier == I915_FORMAT_MOD_Y_TILED ||
> + fb->modifier == I915_FORMAT_MOD_Yf_TILED ||
> + fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
> + fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS ||
> + fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS ||
> + fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS ||
> + fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC)) {
> + drm_dbg_kms(&dev_priv->drm,
> + "Y/Yf tiling not supported in IF-ID mode\n");
> + return -EINVAL;
> + }
> +
> + /* Wa_1606054188:tgl,adl-s */
> + if ((IS_ALDERLAKE_S(dev_priv) || IS_TIGERLAKE(dev_priv)) &&
> + plane_state->ckey.flags & I915_SET_COLORKEY_SOURCE &&
> + intel_format_is_p01x(fb->format->format)) {
> + drm_dbg_kms(&dev_priv->drm,
> + "Source color keying not supported with P01x formats\n");
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int skl_plane_check_dst_coordinates(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);
> + int crtc_x = plane_state->uapi.dst.x1;
> + int crtc_w = drm_rect_width(&plane_state->uapi.dst);
> + int pipe_src_w = crtc_state->pipe_src_w;
> +
> + /*
> + * Display WA #1175: cnl,glk
> + * Planes other than the cursor may cause FIFO underflow and display
> + * corruption if starting less than 4 pixels from the right edge of
> + * the screen.
> + * Besides the above WA fix the similar problem, where planes other
> + * than the cursor ending less than 4 pixels from the left edge of the
> + * screen may cause FIFO underflow and display corruption.
> + */
> + if ((IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) &&
> + (crtc_x + crtc_w < 4 || crtc_x > pipe_src_w - 4)) {
> + drm_dbg_kms(&dev_priv->drm,
> + "requested plane X %s position %d invalid (valid range %d-%d)\n",
> + crtc_x + crtc_w < 4 ? "end" : "start",
> + crtc_x + crtc_w < 4 ? crtc_x + crtc_w : crtc_x,
> + 4, pipe_src_w - 4);
> + return -ERANGE;
> + }
> +
> + return 0;
> +}
> +
> +static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_state)
> +{
> + const struct drm_framebuffer *fb = plane_state->hw.fb;
> + unsigned int rotation = plane_state->hw.rotation;
> + int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
> +
> + /* Display WA #1106 */
> + if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
> + 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 planar YUV\n");
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int skl_plane_max_scale(struct drm_i915_private *dev_priv,
> + const struct drm_framebuffer *fb)
> +{
> + /*
> + * We don't yet know the final source width nor
> + * whether we can use the HQ scaler mode. Assume
> + * the best case.
> + * FIXME need to properly check this later.
> + */
> + if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv) ||
> + !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
> + return 0x30000 - 1;
> + else
> + return 0x20000 - 1;
> +}
> +
> +static int intel_plane_min_width(struct intel_plane *plane,
> + const struct drm_framebuffer *fb,
> + int color_plane,
> + unsigned int rotation)
> +{
> + if (plane->min_width)
> + return plane->min_width(fb, color_plane, rotation);
> + else
> + return 1;
> +}
> +
> +static int intel_plane_max_width(struct intel_plane *plane,
> + const struct drm_framebuffer *fb,
> + int color_plane,
> + unsigned int rotation)
> +{
> + if (plane->max_width)
> + return plane->max_width(fb, color_plane, rotation);
> + else
> + return INT_MAX;
> +}
> +
> +static int intel_plane_max_height(struct intel_plane *plane,
> + const struct drm_framebuffer *fb,
> + int color_plane,
> + unsigned int rotation)
> +{
> + if (plane->max_height)
> + return plane->max_height(fb, color_plane, rotation);
> + else
> + return INT_MAX;
> +}
> +
> +static bool
> +skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state,
> + int main_x, int main_y, u32 main_offset,
> + int ccs_plane)
> +{
> + const struct drm_framebuffer *fb = plane_state->hw.fb;
> + int aux_x = plane_state->color_plane[ccs_plane].x;
> + int aux_y = plane_state->color_plane[ccs_plane].y;
> + u32 aux_offset = plane_state->color_plane[ccs_plane].offset;
> + u32 alignment = intel_surf_alignment(fb, ccs_plane);
> + int hsub;
> + int vsub;
> +
> + intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane);
> + while (aux_offset >= main_offset && aux_y <= main_y) {
> + int x, y;
> +
> + if (aux_x == main_x && aux_y == main_y)
> + break;
> +
> + if (aux_offset == 0)
> + break;
> +
> + x = aux_x / hsub;
> + y = aux_y / vsub;
> + aux_offset = intel_plane_adjust_aligned_offset(&x, &y,
> + plane_state,
> + ccs_plane,
> + aux_offset,
> + aux_offset -
> + alignment);
> + aux_x = x * hsub + aux_x % hsub;
> + aux_y = y * vsub + aux_y % vsub;
> + }
> +
> + if (aux_x != main_x || aux_y != main_y)
> + return false;
> +
> + plane_state->color_plane[ccs_plane].offset = aux_offset;
> + plane_state->color_plane[ccs_plane].x = aux_x;
> + plane_state->color_plane[ccs_plane].y = aux_y;
> +
> + return true;
> +}
> +
> +
> +int skl_calc_main_surface_offset(const struct intel_plane_state *plane_state,
> + int *x, int *y, u32 *offset)
> +{
> + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
> + struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> + const struct drm_framebuffer *fb = plane_state->hw.fb;
> + const int aux_plane = skl_main_to_aux_plane(fb, 0);
> + const u32 aux_offset = plane_state->color_plane[aux_plane].offset;
> + const u32 alignment = intel_surf_alignment(fb, 0);
> + const int w = drm_rect_width(&plane_state->uapi.src) >> 16;
> +
> + intel_add_fb_offsets(x, y, plane_state, 0);
> + *offset = intel_plane_compute_aligned_offset(x, y, plane_state, 0);
> + if (drm_WARN_ON(&dev_priv->drm, alignment && !is_power_of_2(alignment)))
> + return -EINVAL;
> +
> + /*
> + * AUX surface offset is specified as the distance from the
> + * main surface offset, and it must be non-negative. Make
> + * sure that is what we will get.
> + */
> + if (aux_plane && *offset > aux_offset)
> + *offset = intel_plane_adjust_aligned_offset(x, y, plane_state, 0,
> + *offset,
> + aux_offset & ~(alignment - 1));
> +
> + /*
> + * When using an X-tiled surface, the plane blows up
> + * if the x offset + width exceed the stride.
> + *
> + * TODO: linear and Y-tiled seem fine, Yf untested,
> + */
> + if (fb->modifier == I915_FORMAT_MOD_X_TILED) {
> + int cpp = fb->format->cpp[0];
> +
> + while ((*x + w) * cpp > plane_state->color_plane[0].stride) {
> + if (*offset == 0) {
> + drm_dbg_kms(&dev_priv->drm,
> + "Unable to find suitable display surface offset due to X-tiling\n");
> + return -EINVAL;
> + }
> +
> + *offset = intel_plane_adjust_aligned_offset(x, y, plane_state, 0,
> + *offset,
> + *offset - alignment);
> + }
> + }
> +
> + return 0;
> +}
> +
> +static int skl_check_main_surface(struct intel_plane_state *plane_state)
> +{
> + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
> + struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> + const struct drm_framebuffer *fb = plane_state->hw.fb;
> + const unsigned int rotation = plane_state->hw.rotation;
> + int x = plane_state->uapi.src.x1 >> 16;
> + int y = plane_state->uapi.src.y1 >> 16;
> + const int w = drm_rect_width(&plane_state->uapi.src) >> 16;
> + const int h = drm_rect_height(&plane_state->uapi.src) >> 16;
> + const int min_width = intel_plane_min_width(plane, fb, 0, rotation);
> + const int max_width = intel_plane_max_width(plane, fb, 0, rotation);
> + const int max_height = intel_plane_max_height(plane, fb, 0, rotation);
> + const int aux_plane = skl_main_to_aux_plane(fb, 0);
> + const u32 alignment = intel_surf_alignment(fb, 0);
> + u32 offset;
> + int ret;
> +
> + if (w > max_width || w < min_width || h > max_height) {
> + drm_dbg_kms(&dev_priv->drm,
> + "requested Y/RGB source size %dx%d outside limits (min: %dx1 max: %dx%d)\n",
> + w, h, min_width, max_width, max_height);
> + return -EINVAL;
> + }
> +
> + ret = skl_calc_main_surface_offset(plane_state, &x, &y, &offset);
> + if (ret)
> + return ret;
> +
> + /*
> + * CCS AUX surface doesn't have its own x/y offsets, we must make sure
> + * they match with the main surface x/y offsets.
> + */
> + if (is_ccs_modifier(fb->modifier)) {
> + while (!skl_check_main_ccs_coordinates(plane_state, x, y,
> + offset, aux_plane)) {
> + if (offset == 0)
> + break;
> +
> + offset = intel_plane_adjust_aligned_offset(&x, &y, plane_state, 0,
> + offset, offset - alignment);
> + }
> +
> + if (x != plane_state->color_plane[aux_plane].x ||
> + y != plane_state->color_plane[aux_plane].y) {
> + drm_dbg_kms(&dev_priv->drm,
> + "Unable to find suitable display surface offset due to CCS\n");
> + return -EINVAL;
> + }
> + }
> +
> + drm_WARN_ON(&dev_priv->drm, x > 8191 || y > 8191);
> +
> + plane_state->color_plane[0].offset = offset;
> + plane_state->color_plane[0].x = x;
> + plane_state->color_plane[0].y = y;
> +
> + /*
> + * Put the final coordinates back so that the src
> + * coordinate checks will see the right values.
> + */
> + drm_rect_translate_to(&plane_state->uapi.src,
> + x << 16, y << 16);
> +
> + return 0;
> +}
> +
> +static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state)
> +{
> + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
> + struct drm_i915_private *i915 = to_i915(plane->base.dev);
> + const struct drm_framebuffer *fb = plane_state->hw.fb;
> + unsigned int rotation = plane_state->hw.rotation;
> + int uv_plane = 1;
> + int max_width = intel_plane_max_width(plane, fb, uv_plane, rotation);
> + int max_height = intel_plane_max_height(plane, fb, uv_plane, rotation);
> + int x = plane_state->uapi.src.x1 >> 17;
> + int y = plane_state->uapi.src.y1 >> 17;
> + int w = drm_rect_width(&plane_state->uapi.src) >> 17;
> + int h = drm_rect_height(&plane_state->uapi.src) >> 17;
> + u32 offset;
> +
> + /* FIXME not quite sure how/if these apply to the chroma plane */
> + if (w > max_width || h > max_height) {
> + drm_dbg_kms(&i915->drm,
> + "CbCr source size %dx%d too big (limit %dx%d)\n",
> + w, h, max_width, max_height);
> + return -EINVAL;
> + }
> +
> + intel_add_fb_offsets(&x, &y, plane_state, uv_plane);
> + offset = intel_plane_compute_aligned_offset(&x, &y,
> + plane_state, uv_plane);
> +
> + if (is_ccs_modifier(fb->modifier)) {
> + int ccs_plane = main_to_ccs_plane(fb, uv_plane);
> + u32 aux_offset = plane_state->color_plane[ccs_plane].offset;
> + u32 alignment = intel_surf_alignment(fb, uv_plane);
> +
> + if (offset > aux_offset)
> + offset = intel_plane_adjust_aligned_offset(&x, &y,
> + plane_state,
> + uv_plane,
> + offset,
> + aux_offset & ~(alignment - 1));
> +
> + while (!skl_check_main_ccs_coordinates(plane_state, x, y,
> + offset, ccs_plane)) {
> + if (offset == 0)
> + break;
> +
> + offset = intel_plane_adjust_aligned_offset(&x, &y,
> + plane_state,
> + uv_plane,
> + offset, offset - alignment);
> + }
> +
> + if (x != plane_state->color_plane[ccs_plane].x ||
> + y != plane_state->color_plane[ccs_plane].y) {
> + drm_dbg_kms(&i915->drm,
> + "Unable to find suitable display surface offset due to CCS\n");
> + return -EINVAL;
> + }
> + }
> +
> + drm_WARN_ON(&i915->drm, x > 8191 || y > 8191);
> +
> + plane_state->color_plane[uv_plane].offset = offset;
> + plane_state->color_plane[uv_plane].x = x;
> + plane_state->color_plane[uv_plane].y = y;
> +
> + return 0;
> +}
> +
> +static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state)
> +{
> + const struct drm_framebuffer *fb = plane_state->hw.fb;
> + int src_x = plane_state->uapi.src.x1 >> 16;
> + int src_y = plane_state->uapi.src.y1 >> 16;
> + u32 offset;
> + int ccs_plane;
> +
> + for (ccs_plane = 0; ccs_plane < fb->format->num_planes; ccs_plane++) {
> + int main_hsub, main_vsub;
> + int hsub, vsub;
> + int x, y;
> +
> + if (!is_ccs_plane(fb, ccs_plane) ||
> + is_gen12_ccs_cc_plane(fb, ccs_plane))
> + continue;
> +
> + intel_fb_plane_get_subsampling(&main_hsub, &main_vsub, fb,
> + skl_ccs_to_main_plane(fb, ccs_plane));
> + intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane);
> +
> + hsub *= main_hsub;
> + vsub *= main_vsub;
> + x = src_x / hsub;
> + y = src_y / vsub;
> +
> + intel_add_fb_offsets(&x, &y, plane_state, ccs_plane);
> +
> + offset = intel_plane_compute_aligned_offset(&x, &y,
> + plane_state,
> + ccs_plane);
> +
> + plane_state->color_plane[ccs_plane].offset = offset;
> + plane_state->color_plane[ccs_plane].x = (x * hsub +
> + src_x % hsub) /
> + main_hsub;
> + plane_state->color_plane[ccs_plane].y = (y * vsub +
> + src_y % vsub) /
> + main_vsub;
> + }
> +
> + return 0;
> +}
> +
> +static int skl_check_plane_surface(struct intel_plane_state *plane_state)
> +{
> + const struct drm_framebuffer *fb = plane_state->hw.fb;
> + int ret, i;
> +
> + ret = intel_plane_compute_gtt(plane_state);
> + if (ret)
> + return ret;
> +
> + if (!plane_state->uapi.visible)
> + return 0;
> +
> + /*
> + * Handle the AUX surface first since the main surface setup depends on
> + * it.
> + */
> + if (is_ccs_modifier(fb->modifier)) {
> + ret = skl_check_ccs_aux_surface(plane_state);
> + if (ret)
> + return ret;
> + }
> +
> + if (intel_format_info_is_yuv_semiplanar(fb->format,
> + fb->modifier)) {
> + ret = skl_check_nv12_aux_surface(plane_state);
> + if (ret)
> + return ret;
> + }
> +
> + for (i = fb->format->num_planes; i < ARRAY_SIZE(plane_state->color_plane); i++) {
> + plane_state->color_plane[i].offset = 0;
> + plane_state->color_plane[i].x = 0;
> + plane_state->color_plane[i].y = 0;
> + }
> +
> + ret = skl_check_main_surface(plane_state);
> + if (ret)
> + return ret;
> +
> + return 0;
> +}
> +
> +static bool intel_fb_scalable(const struct drm_framebuffer *fb)
> +{
> + if (!fb)
> + return false;
> +
> + switch (fb->format->format) {
> + case DRM_FORMAT_C8:
> + return false;
> + case DRM_FORMAT_XRGB16161616F:
> + case DRM_FORMAT_ARGB16161616F:
> + case DRM_FORMAT_XBGR16161616F:
> + case DRM_FORMAT_ABGR16161616F:
> + return INTEL_GEN(to_i915(fb->dev)) >= 11;
> + default:
> + return true;
> + }
> +}
> +
> +static int skl_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);
> + struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> + const struct drm_framebuffer *fb = plane_state->hw.fb;
> + int min_scale = DRM_PLANE_HELPER_NO_SCALING;
> + int max_scale = DRM_PLANE_HELPER_NO_SCALING;
> + int ret;
> +
> + ret = skl_plane_check_fb(crtc_state, plane_state);
> + if (ret)
> + return ret;
> +
> + /* use scaler when colorkey is not required */
> + if (!plane_state->ckey.flags && intel_fb_scalable(fb)) {
> + min_scale = 1;
> + max_scale = skl_plane_max_scale(dev_priv, fb);
> + }
> +
> + ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
> + min_scale, max_scale, true);
> + if (ret)
> + return ret;
> +
> + ret = skl_check_plane_surface(plane_state);
> + if (ret)
> + return ret;
> +
> + if (!plane_state->uapi.visible)
> + return 0;
> +
> + ret = skl_plane_check_dst_coordinates(crtc_state, plane_state);
> + if (ret)
> + return ret;
> +
> + ret = intel_plane_check_src_coordinates(plane_state);
> + if (ret)
> + return ret;
> +
> + ret = skl_plane_check_nv12_rotation(plane_state);
> + if (ret)
> + return ret;
> +
> + /* HW only has 8 bits pixel precision, disable plane if invisible */
> + if (!(plane_state->hw.alpha >> 8))
> + plane_state->uapi.visible = false;
> +
> + plane_state->ctl = skl_plane_ctl(crtc_state, plane_state);
> +
> + if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
> + plane_state->color_ctl = glk_plane_color_ctl(crtc_state,
> + plane_state);
> +
> + if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
> + icl_is_hdr_plane(dev_priv, plane->id))
> + /* Enable and use MPEG-2 chroma siting */
> + plane_state->cus_ctl = PLANE_CUS_ENABLE |
> + PLANE_CUS_HPHASE_0 |
> + PLANE_CUS_VPHASE_SIGN_NEGATIVE | PLANE_CUS_VPHASE_0_25;
> + else
> + plane_state->cus_ctl = 0;
> +
> + return 0;
> +}
> +
> +static bool skl_plane_has_fbc(struct drm_i915_private *dev_priv,
> + enum pipe pipe, enum plane_id plane_id)
> +{
> + if (!HAS_FBC(dev_priv))
> + return false;
> +
> + return pipe == PIPE_A && plane_id == PLANE_PRIMARY;
> +}
> +
> +static bool skl_plane_has_planar(struct drm_i915_private *dev_priv,
> + enum pipe pipe, enum plane_id plane_id)
> +{
> + /* Display WA #0870: skl, bxt */
> + if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))
> + return false;
> +
> + if (IS_GEN(dev_priv, 9) && !IS_GEMINILAKE(dev_priv) && pipe == PIPE_C)
> + return false;
> +
> + if (plane_id != PLANE_PRIMARY && plane_id != PLANE_SPRITE0)
> + return false;
> +
> + return true;
> +}
> +
> +static const u32 *skl_get_plane_formats(struct drm_i915_private *dev_priv,
> + enum pipe pipe, enum plane_id plane_id,
> + int *num_formats)
> +{
> + if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
> + *num_formats = ARRAY_SIZE(skl_planar_formats);
> + return skl_planar_formats;
> + } else {
> + *num_formats = ARRAY_SIZE(skl_plane_formats);
> + return skl_plane_formats;
> + }
> +}
> +
> +static const u32 *glk_get_plane_formats(struct drm_i915_private *dev_priv,
> + enum pipe pipe, enum plane_id plane_id,
> + int *num_formats)
> +{
> + if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
> + *num_formats = ARRAY_SIZE(glk_planar_formats);
> + return glk_planar_formats;
> + } else {
> + *num_formats = ARRAY_SIZE(skl_plane_formats);
> + return skl_plane_formats;
> + }
> +}
> +
> +static const u32 *icl_get_plane_formats(struct drm_i915_private *dev_priv,
> + enum pipe pipe, enum plane_id plane_id,
> + int *num_formats)
> +{
> + if (icl_is_hdr_plane(dev_priv, plane_id)) {
> + *num_formats = ARRAY_SIZE(icl_hdr_plane_formats);
> + return icl_hdr_plane_formats;
> + } else if (icl_is_nv12_y_plane(dev_priv, plane_id)) {
> + *num_formats = ARRAY_SIZE(icl_sdr_y_plane_formats);
> + return icl_sdr_y_plane_formats;
> + } else {
> + *num_formats = ARRAY_SIZE(icl_sdr_uv_plane_formats);
> + return icl_sdr_uv_plane_formats;
> + }
> +}
> +
> +static bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
> + enum pipe pipe, enum plane_id plane_id)
> +{
> + if (plane_id == PLANE_CURSOR)
> + return false;
> +
> + if (INTEL_GEN(dev_priv) >= 10)
> + return true;
> +
> + if (IS_GEMINILAKE(dev_priv))
> + return pipe != PIPE_C;
> +
> + return pipe != PIPE_C &&
> + (plane_id == PLANE_PRIMARY ||
> + plane_id == PLANE_SPRITE0);
> +}
> +
> +static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
> + u32 format, u64 modifier)
> +{
> + struct intel_plane *plane = to_intel_plane(_plane);
> +
> + switch (modifier) {
> + case DRM_FORMAT_MOD_LINEAR:
> + case I915_FORMAT_MOD_X_TILED:
> + case I915_FORMAT_MOD_Y_TILED:
> + case I915_FORMAT_MOD_Yf_TILED:
> + break;
> + case I915_FORMAT_MOD_Y_TILED_CCS:
> + case I915_FORMAT_MOD_Yf_TILED_CCS:
> + if (!plane->has_ccs)
> + return false;
> + break;
> + default:
> + return false;
> + }
> +
> + switch (format) {
> + case DRM_FORMAT_XRGB8888:
> + case DRM_FORMAT_XBGR8888:
> + case DRM_FORMAT_ARGB8888:
> + case DRM_FORMAT_ABGR8888:
> + if (is_ccs_modifier(modifier))
> + return true;
> + fallthrough;
> + case DRM_FORMAT_RGB565:
> + case DRM_FORMAT_XRGB2101010:
> + case DRM_FORMAT_XBGR2101010:
> + case DRM_FORMAT_ARGB2101010:
> + case DRM_FORMAT_ABGR2101010:
> + case DRM_FORMAT_YUYV:
> + case DRM_FORMAT_YVYU:
> + case DRM_FORMAT_UYVY:
> + case DRM_FORMAT_VYUY:
> + case DRM_FORMAT_NV12:
> + case DRM_FORMAT_XYUV8888:
> + 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;
> + fallthrough;
> + 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)
> + return true;
> + fallthrough;
> + default:
> + return false;
> + }
> +}
> +
> +static bool gen12_plane_supports_mc_ccs(struct drm_i915_private *dev_priv,
> + enum plane_id plane_id)
> +{
> + /* Wa_14010477008:tgl[a0..c0],rkl[all],dg1[all] */
> + if (IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv) ||
> + IS_TGL_DISP_STEPPING(dev_priv, STEP_A0, STEP_C0))
> + return false;
> +
> + return plane_id < PLANE_SPRITE4;
> +}
> +
> +static bool gen12_plane_format_mod_supported(struct drm_plane *_plane,
> + u32 format, u64 modifier)
> +{
> + struct drm_i915_private *dev_priv = to_i915(_plane->dev);
> + struct intel_plane *plane = to_intel_plane(_plane);
> +
> + switch (modifier) {
> + case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
> + if (!gen12_plane_supports_mc_ccs(dev_priv, plane->id))
> + return false;
> + fallthrough;
> + case DRM_FORMAT_MOD_LINEAR:
> + case I915_FORMAT_MOD_X_TILED:
> + case I915_FORMAT_MOD_Y_TILED:
> + case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
> + case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
> + break;
> + default:
> + return false;
> + }
> +
> + switch (format) {
> + case DRM_FORMAT_XRGB8888:
> + case DRM_FORMAT_XBGR8888:
> + case DRM_FORMAT_ARGB8888:
> + case DRM_FORMAT_ABGR8888:
> + if (is_ccs_modifier(modifier))
> + return true;
> + fallthrough;
> + case DRM_FORMAT_YUYV:
> + case DRM_FORMAT_YVYU:
> + case DRM_FORMAT_UYVY:
> + case DRM_FORMAT_VYUY:
> + case DRM_FORMAT_NV12:
> + case DRM_FORMAT_XYUV8888:
> + case DRM_FORMAT_P010:
> + case DRM_FORMAT_P012:
> + case DRM_FORMAT_P016:
> + if (modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS)
> + return true;
> + fallthrough;
> + case DRM_FORMAT_RGB565:
> + case DRM_FORMAT_XRGB2101010:
> + case DRM_FORMAT_XBGR2101010:
> + case DRM_FORMAT_ARGB2101010:
> + case DRM_FORMAT_ABGR2101010:
> + case DRM_FORMAT_XVYU2101010:
> + 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)
> + return true;
> + fallthrough;
> + default:
> + return false;
> + }
> +}
> +
> +static const u64 *gen12_get_plane_modifiers(struct drm_i915_private *dev_priv,
> + enum plane_id plane_id)
> +{
> + if (gen12_plane_supports_mc_ccs(dev_priv, plane_id))
> + return gen12_plane_format_modifiers_mc_ccs;
> + else
> + return gen12_plane_format_modifiers_rc_ccs;
> +}
> +
> +static const struct drm_plane_funcs skl_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 = skl_plane_format_mod_supported,
> +};
> +
> +static const struct drm_plane_funcs gen12_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 = gen12_plane_format_mod_supported,
> +};
> +
> +static void
> +skl_plane_enable_flip_done(struct intel_plane *plane)
> +{
> + struct drm_i915_private *i915 = to_i915(plane->base.dev);
> + enum pipe pipe = plane->pipe;
> +
> + spin_lock_irq(&i915->irq_lock);
> + bdw_enable_pipe_irq(i915, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id));
> + spin_unlock_irq(&i915->irq_lock);
> +}
> +
> +static void
> +skl_plane_disable_flip_done(struct intel_plane *plane)
> +{
> + struct drm_i915_private *i915 = to_i915(plane->base.dev);
> + enum pipe pipe = plane->pipe;
> +
> + spin_lock_irq(&i915->irq_lock);
> + bdw_disable_pipe_irq(i915, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id));
> + spin_unlock_irq(&i915->irq_lock);
> +}
> +
> +struct intel_plane *
> +skl_universal_plane_create(struct drm_i915_private *dev_priv,
> + enum pipe pipe, enum plane_id plane_id)
> +{
> + const struct drm_plane_funcs *plane_funcs;
> + struct intel_plane *plane;
> + enum drm_plane_type plane_type;
> + unsigned int supported_rotations;
> + unsigned int supported_csc;
> + const u64 *modifiers;
> + const u32 *formats;
> + int num_formats;
> + int ret;
> +
> + plane = intel_plane_alloc();
> + if (IS_ERR(plane))
> + return plane;
> +
> + plane->pipe = pipe;
> + plane->id = plane_id;
> + plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane_id);
> +
> + plane->has_fbc = skl_plane_has_fbc(dev_priv, pipe, plane_id);
> + if (plane->has_fbc) {
> + struct intel_fbc *fbc = &dev_priv->fbc;
> +
> + fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
> + }
> +
> + if (INTEL_GEN(dev_priv) >= 11) {
> + plane->min_width = icl_plane_min_width;
> + plane->max_width = icl_plane_max_width;
> + plane->max_height = icl_plane_max_height;
> + } else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) {
> + plane->max_width = glk_plane_max_width;
> + plane->max_height = skl_plane_max_height;
> + } else {
> + plane->max_width = skl_plane_max_width;
> + plane->max_height = skl_plane_max_height;
> + }
> +
> + plane->max_stride = skl_plane_max_stride;
> + plane->update_plane = skl_update_plane;
> + plane->disable_plane = skl_disable_plane;
> + plane->get_hw_state = skl_plane_get_hw_state;
> + plane->check_plane = skl_plane_check;
> + plane->min_cdclk = skl_plane_min_cdclk;
> +
> + if (plane_id == PLANE_PRIMARY) {
> + plane->need_async_flip_disable_wa = IS_GEN_RANGE(dev_priv, 9, 10);
> + plane->async_flip = skl_plane_async_flip;
> + plane->enable_flip_done = skl_plane_enable_flip_done;
> + plane->disable_flip_done = skl_plane_disable_flip_done;
> + }
> +
> + if (INTEL_GEN(dev_priv) >= 11)
> + formats = icl_get_plane_formats(dev_priv, pipe,
> + plane_id, &num_formats);
> + else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
> + formats = glk_get_plane_formats(dev_priv, pipe,
> + plane_id, &num_formats);
> + else
> + formats = skl_get_plane_formats(dev_priv, pipe,
> + plane_id, &num_formats);
> +
> + plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, plane_id);
> + if (INTEL_GEN(dev_priv) >= 12) {
> + modifiers = gen12_get_plane_modifiers(dev_priv, plane_id);
> + plane_funcs = &gen12_plane_funcs;
> + } else {
> + if (plane->has_ccs)
> + modifiers = skl_plane_format_modifiers_ccs;
> + else
> + modifiers = skl_plane_format_modifiers_noccs;
> + plane_funcs = &skl_plane_funcs;
> + }
> +
> + if (plane_id == PLANE_PRIMARY)
> + plane_type = DRM_PLANE_TYPE_PRIMARY;
> + else
> + plane_type = DRM_PLANE_TYPE_OVERLAY;
> +
> + ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
> + 0, plane_funcs,
> + formats, num_formats, modifiers,
> + plane_type,
> + "plane %d%c", plane_id + 1,
> + pipe_name(pipe));
> + if (ret)
> + goto fail;
> +
> + supported_rotations =
> + DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
> + DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
> +
> + if (INTEL_GEN(dev_priv) >= 10)
> + supported_rotations |= DRM_MODE_REFLECT_X;
> +
> + drm_plane_create_rotation_property(&plane->base,
> + DRM_MODE_ROTATE_0,
> + supported_rotations);
> +
> + supported_csc = BIT(DRM_COLOR_YCBCR_BT601) | BIT(DRM_COLOR_YCBCR_BT709);
> +
> + if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
> + supported_csc |= BIT(DRM_COLOR_YCBCR_BT2020);
> +
> + drm_plane_create_color_properties(&plane->base,
> + supported_csc,
> + BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
> + BIT(DRM_COLOR_YCBCR_FULL_RANGE),
> + DRM_COLOR_YCBCR_BT709,
> + DRM_COLOR_YCBCR_LIMITED_RANGE);
> +
> + drm_plane_create_alpha_property(&plane->base);
> + drm_plane_create_blend_mode_property(&plane->base,
> + BIT(DRM_MODE_BLEND_PIXEL_NONE) |
> + BIT(DRM_MODE_BLEND_PREMULTI) |
> + BIT(DRM_MODE_BLEND_COVERAGE));
> +
> + drm_plane_create_zpos_immutable_property(&plane->base, plane_id);
> +
> + if (INTEL_GEN(dev_priv) >= 12)
> + drm_plane_enable_fb_damage_clips(&plane->base);
> +
> + if (INTEL_GEN(dev_priv) >= 10)
> + drm_plane_create_scaling_filter_property(&plane->base,
> + BIT(DRM_SCALING_FILTER_DEFAULT) |
> + BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
> +
> + drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
> +
> + return plane;
> +
> +fail:
> + intel_plane_free(plane);
> +
> + return ERR_PTR(ret);
> +}
> +
> +void
> +skl_get_initial_plane_config(struct intel_crtc *crtc,
> + struct intel_initial_plane_config *plane_config)
> +{
> + struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state);
> + struct drm_device *dev = crtc->base.dev;
> + struct drm_i915_private *dev_priv = to_i915(dev);
> + struct intel_plane *plane = to_intel_plane(crtc->base.primary);
> + enum plane_id plane_id = plane->id;
> + enum pipe pipe;
> + u32 val, base, offset, stride_mult, tiling, alpha;
> + int fourcc, pixel_format;
> + unsigned int aligned_height;
> + struct drm_framebuffer *fb;
> + struct intel_framebuffer *intel_fb;
> +
> + if (!plane->get_hw_state(plane, &pipe))
> + return;
> +
> + drm_WARN_ON(dev, pipe != crtc->pipe);
> +
> + if (crtc_state->bigjoiner) {
> + drm_dbg_kms(&dev_priv->drm,
> + "Unsupported bigjoiner configuration for initial FB\n");
> + return;
> + }
> +
> + intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
> + if (!intel_fb) {
> + drm_dbg_kms(&dev_priv->drm, "failed to alloc fb\n");
> + return;
> + }
> +
> + fb = &intel_fb->base;
> +
> + fb->dev = dev;
> +
> + val = intel_de_read(dev_priv, PLANE_CTL(pipe, plane_id));
> +
> + if (INTEL_GEN(dev_priv) >= 11)
> + pixel_format = val & ICL_PLANE_CTL_FORMAT_MASK;
> + else
> + pixel_format = val & PLANE_CTL_FORMAT_MASK;
> +
> + if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) {
> + alpha = intel_de_read(dev_priv,
> + PLANE_COLOR_CTL(pipe, plane_id));
> + alpha &= PLANE_COLOR_ALPHA_MASK;
> + } else {
> + alpha = val & PLANE_CTL_ALPHA_MASK;
> + }
> +
> + fourcc = skl_format_to_fourcc(pixel_format,
> + val & PLANE_CTL_ORDER_RGBX, alpha);
> + fb->format = drm_format_info(fourcc);
> +
> + tiling = val & PLANE_CTL_TILED_MASK;
> + switch (tiling) {
> + case PLANE_CTL_TILED_LINEAR:
> + fb->modifier = DRM_FORMAT_MOD_LINEAR;
> + break;
> + case PLANE_CTL_TILED_X:
> + plane_config->tiling = I915_TILING_X;
> + fb->modifier = I915_FORMAT_MOD_X_TILED;
> + break;
> + case PLANE_CTL_TILED_Y:
> + plane_config->tiling = I915_TILING_Y;
> + if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
> + fb->modifier = INTEL_GEN(dev_priv) >= 12 ?
> + I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS :
> + I915_FORMAT_MOD_Y_TILED_CCS;
> + else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE)
> + fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS;
> + else
> + fb->modifier = I915_FORMAT_MOD_Y_TILED;
> + break;
> + case PLANE_CTL_TILED_YF:
> + if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
> + fb->modifier = I915_FORMAT_MOD_Yf_TILED_CCS;
> + else
> + fb->modifier = I915_FORMAT_MOD_Yf_TILED;
> + break;
> + default:
> + MISSING_CASE(tiling);
> + goto error;
> + }
> +
> + /*
> + * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr
> + * while i915 HW rotation is clockwise, thats why this swapping.
> + */
> + switch (val & PLANE_CTL_ROTATE_MASK) {
> + case PLANE_CTL_ROTATE_0:
> + plane_config->rotation = DRM_MODE_ROTATE_0;
> + break;
> + case PLANE_CTL_ROTATE_90:
> + plane_config->rotation = DRM_MODE_ROTATE_270;
> + break;
> + case PLANE_CTL_ROTATE_180:
> + plane_config->rotation = DRM_MODE_ROTATE_180;
> + break;
> + case PLANE_CTL_ROTATE_270:
> + plane_config->rotation = DRM_MODE_ROTATE_90;
> + break;
> + }
> +
> + if (INTEL_GEN(dev_priv) >= 10 &&
> + val & PLANE_CTL_FLIP_HORIZONTAL)
> + plane_config->rotation |= DRM_MODE_REFLECT_X;
> +
> + /* 90/270 degree rotation would require extra work */
> + if (drm_rotation_90_or_270(plane_config->rotation))
> + goto error;
> +
> + base = intel_de_read(dev_priv, PLANE_SURF(pipe, plane_id)) & 0xfffff000;
> + plane_config->base = base;
> +
> + offset = intel_de_read(dev_priv, PLANE_OFFSET(pipe, plane_id));
> +
> + val = intel_de_read(dev_priv, PLANE_SIZE(pipe, plane_id));
> + fb->height = ((val >> 16) & 0xffff) + 1;
> + fb->width = ((val >> 0) & 0xffff) + 1;
> +
> + val = intel_de_read(dev_priv, PLANE_STRIDE(pipe, plane_id));
> + stride_mult = skl_plane_stride_mult(fb, 0, DRM_MODE_ROTATE_0);
> + fb->pitches[0] = (val & 0x3ff) * stride_mult;
> +
> + aligned_height = intel_fb_align_height(fb, 0, fb->height);
> +
> + plane_config->size = fb->pitches[0] * aligned_height;
> +
> + drm_dbg_kms(&dev_priv->drm,
> + "%s/%s with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
> + crtc->base.name, plane->base.name, fb->width, fb->height,
> + fb->format->cpp[0] * 8, base, fb->pitches[0],
> + plane_config->size);
> +
> + plane_config->fb = intel_fb;
> + return;
> +
> +error:
> + kfree(intel_fb);
> +}
> +
> diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.h b/drivers/gpu/drm/i915/display/skl_universal_plane.h
> new file mode 100644
> index 000000000000..70eb5010cd28
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.h
> @@ -0,0 +1,33 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2020 Intel Corporation
> + */
> +
> +#ifndef _SKL_UNIVERSAL_PLANE_H_
> +#define _SKL_UNIVERSAL_PLANE_H_
> +
> +#include <linux/types.h>
> +
> +struct drm_framebuffer;
> +struct drm_i915_private;
> +struct intel_crtc;
> +struct intel_initial_plane_config;
> +struct intel_plane_state;
> +
> +enum pipe;
> +enum plane_id;
> +
> +struct intel_plane *
> +skl_universal_plane_create(struct drm_i915_private *dev_priv,
> + enum pipe pipe, enum plane_id plane_id);
> +
> +void skl_get_initial_plane_config(struct intel_crtc *crtc,
> + struct intel_initial_plane_config *plane_config);
> +
> +int skl_format_to_fourcc(int format, bool rgb_order, bool alpha);
> +
> +int skl_ccs_to_main_plane(const struct drm_framebuffer *fb, int ccs_plane);
> +int skl_calc_main_surface_offset(const struct intel_plane_state *plane_state,
> + int *x, int *y, u32 *offset);
> +
> +#endif
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index c58e5077590d..8c42fa51c0f6 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -38,6 +38,7 @@
> #include "display/intel_display_types.h"
> #include "display/intel_fbc.h"
> #include "display/intel_sprite.h"
> +#include "display/skl_universal_plane.h"
>
> #include "gt/intel_llc.h"
>
> --
> 2.20.1
--
Ville Syrjälä
Intel
More information about the Intel-gfx
mailing list