linux/drivers/gpu/drm/i915/display/skl_universal_plane.c
<<
>>
Prefs
   1// SPDX-License-Identifier: MIT
   2/*
   3 * Copyright © 2020 Intel Corporation
   4 */
   5
   6#include <drm/drm_atomic_helper.h>
   7#include <drm/drm_damage_helper.h>
   8#include <drm/drm_fourcc.h>
   9#include <drm/drm_plane_helper.h>
  10
  11#include "i915_drv.h"
  12#include "intel_atomic_plane.h"
  13#include "intel_de.h"
  14#include "intel_display_types.h"
  15#include "intel_fb.h"
  16#include "intel_pm.h"
  17#include "intel_psr.h"
  18#include "intel_sprite.h"
  19#include "skl_scaler.h"
  20#include "skl_universal_plane.h"
  21
  22static const u32 skl_plane_formats[] = {
  23        DRM_FORMAT_C8,
  24        DRM_FORMAT_RGB565,
  25        DRM_FORMAT_XRGB8888,
  26        DRM_FORMAT_XBGR8888,
  27        DRM_FORMAT_ARGB8888,
  28        DRM_FORMAT_ABGR8888,
  29        DRM_FORMAT_XRGB2101010,
  30        DRM_FORMAT_XBGR2101010,
  31        DRM_FORMAT_XRGB16161616F,
  32        DRM_FORMAT_XBGR16161616F,
  33        DRM_FORMAT_YUYV,
  34        DRM_FORMAT_YVYU,
  35        DRM_FORMAT_UYVY,
  36        DRM_FORMAT_VYUY,
  37        DRM_FORMAT_XYUV8888,
  38};
  39
  40static const u32 skl_planar_formats[] = {
  41        DRM_FORMAT_C8,
  42        DRM_FORMAT_RGB565,
  43        DRM_FORMAT_XRGB8888,
  44        DRM_FORMAT_XBGR8888,
  45        DRM_FORMAT_ARGB8888,
  46        DRM_FORMAT_ABGR8888,
  47        DRM_FORMAT_XRGB2101010,
  48        DRM_FORMAT_XBGR2101010,
  49        DRM_FORMAT_XRGB16161616F,
  50        DRM_FORMAT_XBGR16161616F,
  51        DRM_FORMAT_YUYV,
  52        DRM_FORMAT_YVYU,
  53        DRM_FORMAT_UYVY,
  54        DRM_FORMAT_VYUY,
  55        DRM_FORMAT_NV12,
  56        DRM_FORMAT_XYUV8888,
  57};
  58
  59static const u32 glk_planar_formats[] = {
  60        DRM_FORMAT_C8,
  61        DRM_FORMAT_RGB565,
  62        DRM_FORMAT_XRGB8888,
  63        DRM_FORMAT_XBGR8888,
  64        DRM_FORMAT_ARGB8888,
  65        DRM_FORMAT_ABGR8888,
  66        DRM_FORMAT_XRGB2101010,
  67        DRM_FORMAT_XBGR2101010,
  68        DRM_FORMAT_XRGB16161616F,
  69        DRM_FORMAT_XBGR16161616F,
  70        DRM_FORMAT_YUYV,
  71        DRM_FORMAT_YVYU,
  72        DRM_FORMAT_UYVY,
  73        DRM_FORMAT_VYUY,
  74        DRM_FORMAT_NV12,
  75        DRM_FORMAT_XYUV8888,
  76        DRM_FORMAT_P010,
  77        DRM_FORMAT_P012,
  78        DRM_FORMAT_P016,
  79};
  80
  81static const u32 icl_sdr_y_plane_formats[] = {
  82        DRM_FORMAT_C8,
  83        DRM_FORMAT_RGB565,
  84        DRM_FORMAT_XRGB8888,
  85        DRM_FORMAT_XBGR8888,
  86        DRM_FORMAT_ARGB8888,
  87        DRM_FORMAT_ABGR8888,
  88        DRM_FORMAT_XRGB2101010,
  89        DRM_FORMAT_XBGR2101010,
  90        DRM_FORMAT_ARGB2101010,
  91        DRM_FORMAT_ABGR2101010,
  92        DRM_FORMAT_YUYV,
  93        DRM_FORMAT_YVYU,
  94        DRM_FORMAT_UYVY,
  95        DRM_FORMAT_VYUY,
  96        DRM_FORMAT_Y210,
  97        DRM_FORMAT_Y212,
  98        DRM_FORMAT_Y216,
  99        DRM_FORMAT_XYUV8888,
 100        DRM_FORMAT_XVYU2101010,
 101        DRM_FORMAT_XVYU12_16161616,
 102        DRM_FORMAT_XVYU16161616,
 103};
 104
 105static const u32 icl_sdr_uv_plane_formats[] = {
 106        DRM_FORMAT_C8,
 107        DRM_FORMAT_RGB565,
 108        DRM_FORMAT_XRGB8888,
 109        DRM_FORMAT_XBGR8888,
 110        DRM_FORMAT_ARGB8888,
 111        DRM_FORMAT_ABGR8888,
 112        DRM_FORMAT_XRGB2101010,
 113        DRM_FORMAT_XBGR2101010,
 114        DRM_FORMAT_ARGB2101010,
 115        DRM_FORMAT_ABGR2101010,
 116        DRM_FORMAT_YUYV,
 117        DRM_FORMAT_YVYU,
 118        DRM_FORMAT_UYVY,
 119        DRM_FORMAT_VYUY,
 120        DRM_FORMAT_NV12,
 121        DRM_FORMAT_P010,
 122        DRM_FORMAT_P012,
 123        DRM_FORMAT_P016,
 124        DRM_FORMAT_Y210,
 125        DRM_FORMAT_Y212,
 126        DRM_FORMAT_Y216,
 127        DRM_FORMAT_XYUV8888,
 128        DRM_FORMAT_XVYU2101010,
 129        DRM_FORMAT_XVYU12_16161616,
 130        DRM_FORMAT_XVYU16161616,
 131};
 132
 133static const u32 icl_hdr_plane_formats[] = {
 134        DRM_FORMAT_C8,
 135        DRM_FORMAT_RGB565,
 136        DRM_FORMAT_XRGB8888,
 137        DRM_FORMAT_XBGR8888,
 138        DRM_FORMAT_ARGB8888,
 139        DRM_FORMAT_ABGR8888,
 140        DRM_FORMAT_XRGB2101010,
 141        DRM_FORMAT_XBGR2101010,
 142        DRM_FORMAT_ARGB2101010,
 143        DRM_FORMAT_ABGR2101010,
 144        DRM_FORMAT_XRGB16161616F,
 145        DRM_FORMAT_XBGR16161616F,
 146        DRM_FORMAT_ARGB16161616F,
 147        DRM_FORMAT_ABGR16161616F,
 148        DRM_FORMAT_YUYV,
 149        DRM_FORMAT_YVYU,
 150        DRM_FORMAT_UYVY,
 151        DRM_FORMAT_VYUY,
 152        DRM_FORMAT_NV12,
 153        DRM_FORMAT_P010,
 154        DRM_FORMAT_P012,
 155        DRM_FORMAT_P016,
 156        DRM_FORMAT_Y210,
 157        DRM_FORMAT_Y212,
 158        DRM_FORMAT_Y216,
 159        DRM_FORMAT_XYUV8888,
 160        DRM_FORMAT_XVYU2101010,
 161        DRM_FORMAT_XVYU12_16161616,
 162        DRM_FORMAT_XVYU16161616,
 163};
 164
 165static const u64 skl_plane_format_modifiers_noccs[] = {
 166        I915_FORMAT_MOD_Yf_TILED,
 167        I915_FORMAT_MOD_Y_TILED,
 168        I915_FORMAT_MOD_X_TILED,
 169        DRM_FORMAT_MOD_LINEAR,
 170        DRM_FORMAT_MOD_INVALID
 171};
 172
 173static const u64 skl_plane_format_modifiers_ccs[] = {
 174        I915_FORMAT_MOD_Yf_TILED_CCS,
 175        I915_FORMAT_MOD_Y_TILED_CCS,
 176        I915_FORMAT_MOD_Yf_TILED,
 177        I915_FORMAT_MOD_Y_TILED,
 178        I915_FORMAT_MOD_X_TILED,
 179        DRM_FORMAT_MOD_LINEAR,
 180        DRM_FORMAT_MOD_INVALID
 181};
 182
 183static const u64 gen12_plane_format_modifiers_mc_ccs[] = {
 184        I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS,
 185        I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS,
 186        I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC,
 187        I915_FORMAT_MOD_Y_TILED,
 188        I915_FORMAT_MOD_X_TILED,
 189        DRM_FORMAT_MOD_LINEAR,
 190        DRM_FORMAT_MOD_INVALID
 191};
 192
 193static const u64 gen12_plane_format_modifiers_rc_ccs[] = {
 194        I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS,
 195        I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC,
 196        I915_FORMAT_MOD_Y_TILED,
 197        I915_FORMAT_MOD_X_TILED,
 198        DRM_FORMAT_MOD_LINEAR,
 199        DRM_FORMAT_MOD_INVALID
 200};
 201
 202static const u64 adlp_step_a_plane_format_modifiers[] = {
 203        I915_FORMAT_MOD_Y_TILED,
 204        I915_FORMAT_MOD_X_TILED,
 205        DRM_FORMAT_MOD_LINEAR,
 206        DRM_FORMAT_MOD_INVALID
 207};
 208
 209int skl_format_to_fourcc(int format, bool rgb_order, bool alpha)
 210{
 211        switch (format) {
 212        case PLANE_CTL_FORMAT_RGB_565:
 213                return DRM_FORMAT_RGB565;
 214        case PLANE_CTL_FORMAT_NV12:
 215                return DRM_FORMAT_NV12;
 216        case PLANE_CTL_FORMAT_XYUV:
 217                return DRM_FORMAT_XYUV8888;
 218        case PLANE_CTL_FORMAT_P010:
 219                return DRM_FORMAT_P010;
 220        case PLANE_CTL_FORMAT_P012:
 221                return DRM_FORMAT_P012;
 222        case PLANE_CTL_FORMAT_P016:
 223                return DRM_FORMAT_P016;
 224        case PLANE_CTL_FORMAT_Y210:
 225                return DRM_FORMAT_Y210;
 226        case PLANE_CTL_FORMAT_Y212:
 227                return DRM_FORMAT_Y212;
 228        case PLANE_CTL_FORMAT_Y216:
 229                return DRM_FORMAT_Y216;
 230        case PLANE_CTL_FORMAT_Y410:
 231                return DRM_FORMAT_XVYU2101010;
 232        case PLANE_CTL_FORMAT_Y412:
 233                return DRM_FORMAT_XVYU12_16161616;
 234        case PLANE_CTL_FORMAT_Y416:
 235                return DRM_FORMAT_XVYU16161616;
 236        default:
 237        case PLANE_CTL_FORMAT_XRGB_8888:
 238                if (rgb_order) {
 239                        if (alpha)
 240                                return DRM_FORMAT_ABGR8888;
 241                        else
 242                                return DRM_FORMAT_XBGR8888;
 243                } else {
 244                        if (alpha)
 245                                return DRM_FORMAT_ARGB8888;
 246                        else
 247                                return DRM_FORMAT_XRGB8888;
 248                }
 249        case PLANE_CTL_FORMAT_XRGB_2101010:
 250                if (rgb_order) {
 251                        if (alpha)
 252                                return DRM_FORMAT_ABGR2101010;
 253                        else
 254                                return DRM_FORMAT_XBGR2101010;
 255                } else {
 256                        if (alpha)
 257                                return DRM_FORMAT_ARGB2101010;
 258                        else
 259                                return DRM_FORMAT_XRGB2101010;
 260                }
 261        case PLANE_CTL_FORMAT_XRGB_16161616F:
 262                if (rgb_order) {
 263                        if (alpha)
 264                                return DRM_FORMAT_ABGR16161616F;
 265                        else
 266                                return DRM_FORMAT_XBGR16161616F;
 267                } else {
 268                        if (alpha)
 269                                return DRM_FORMAT_ARGB16161616F;
 270                        else
 271                                return DRM_FORMAT_XRGB16161616F;
 272                }
 273        }
 274}
 275
 276static u8 icl_nv12_y_plane_mask(struct drm_i915_private *i915)
 277{
 278        if (DISPLAY_VER(i915) >= 13 || HAS_D12_PLANE_MINIMIZATION(i915))
 279                return BIT(PLANE_SPRITE2) | BIT(PLANE_SPRITE3);
 280        else
 281                return BIT(PLANE_SPRITE4) | BIT(PLANE_SPRITE5);
 282}
 283
 284bool icl_is_nv12_y_plane(struct drm_i915_private *dev_priv,
 285                         enum plane_id plane_id)
 286{
 287        return DISPLAY_VER(dev_priv) >= 11 &&
 288                icl_nv12_y_plane_mask(dev_priv) & BIT(plane_id);
 289}
 290
 291bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id)
 292{
 293        return DISPLAY_VER(dev_priv) >= 11 &&
 294                icl_hdr_plane_mask() & BIT(plane_id);
 295}
 296
 297static int icl_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
 298                               const struct intel_plane_state *plane_state)
 299{
 300        unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
 301
 302        /* two pixels per clock */
 303        return DIV_ROUND_UP(pixel_rate, 2);
 304}
 305
 306static void
 307glk_plane_ratio(const struct intel_plane_state *plane_state,
 308                unsigned int *num, unsigned int *den)
 309{
 310        const struct drm_framebuffer *fb = plane_state->hw.fb;
 311
 312        if (fb->format->cpp[0] == 8) {
 313                *num = 10;
 314                *den = 8;
 315        } else {
 316                *num = 1;
 317                *den = 1;
 318        }
 319}
 320
 321static int glk_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
 322                               const struct intel_plane_state *plane_state)
 323{
 324        unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
 325        unsigned int num, den;
 326
 327        glk_plane_ratio(plane_state, &num, &den);
 328
 329        /* two pixels per clock */
 330        return DIV_ROUND_UP(pixel_rate * num, 2 * den);
 331}
 332
 333static void
 334skl_plane_ratio(const struct intel_plane_state *plane_state,
 335                unsigned int *num, unsigned int *den)
 336{
 337        const struct drm_framebuffer *fb = plane_state->hw.fb;
 338
 339        if (fb->format->cpp[0] == 8) {
 340                *num = 9;
 341                *den = 8;
 342        } else {
 343                *num = 1;
 344                *den = 1;
 345        }
 346}
 347
 348static int skl_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
 349                               const struct intel_plane_state *plane_state)
 350{
 351        unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
 352        unsigned int num, den;
 353
 354        skl_plane_ratio(plane_state, &num, &den);
 355
 356        return DIV_ROUND_UP(pixel_rate * num, den);
 357}
 358
 359static int skl_plane_max_width(const struct drm_framebuffer *fb,
 360                               int color_plane,
 361                               unsigned int rotation)
 362{
 363        int cpp = fb->format->cpp[color_plane];
 364
 365        switch (fb->modifier) {
 366        case DRM_FORMAT_MOD_LINEAR:
 367        case I915_FORMAT_MOD_X_TILED:
 368                /*
 369                 * Validated limit is 4k, but has 5k should
 370                 * work apart from the following features:
 371                 * - Ytile (already limited to 4k)
 372                 * - FP16 (already limited to 4k)
 373                 * - render compression (already limited to 4k)
 374                 * - KVMR sprite and cursor (don't care)
 375                 * - horizontal panning (TODO verify this)
 376                 * - pipe and plane scaling (TODO verify this)
 377                 */
 378                if (cpp == 8)
 379                        return 4096;
 380                else
 381                        return 5120;
 382        case I915_FORMAT_MOD_Y_TILED_CCS:
 383        case I915_FORMAT_MOD_Yf_TILED_CCS:
 384        case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
 385                /* FIXME AUX plane? */
 386        case I915_FORMAT_MOD_Y_TILED:
 387        case I915_FORMAT_MOD_Yf_TILED:
 388                if (cpp == 8)
 389                        return 2048;
 390                else
 391                        return 4096;
 392        default:
 393                MISSING_CASE(fb->modifier);
 394                return 2048;
 395        }
 396}
 397
 398static int glk_plane_max_width(const struct drm_framebuffer *fb,
 399                               int color_plane,
 400                               unsigned int rotation)
 401{
 402        int cpp = fb->format->cpp[color_plane];
 403
 404        switch (fb->modifier) {
 405        case DRM_FORMAT_MOD_LINEAR:
 406        case I915_FORMAT_MOD_X_TILED:
 407                if (cpp == 8)
 408                        return 4096;
 409                else
 410                        return 5120;
 411        case I915_FORMAT_MOD_Y_TILED_CCS:
 412        case I915_FORMAT_MOD_Yf_TILED_CCS:
 413                /* FIXME AUX plane? */
 414        case I915_FORMAT_MOD_Y_TILED:
 415        case I915_FORMAT_MOD_Yf_TILED:
 416                if (cpp == 8)
 417                        return 2048;
 418                else
 419                        return 5120;
 420        default:
 421                MISSING_CASE(fb->modifier);
 422                return 2048;
 423        }
 424}
 425
 426static int icl_plane_min_width(const struct drm_framebuffer *fb,
 427                               int color_plane,
 428                               unsigned int rotation)
 429{
 430        /* Wa_14011264657, Wa_14011050563: gen11+ */
 431        switch (fb->format->format) {
 432        case DRM_FORMAT_C8:
 433                return 18;
 434        case DRM_FORMAT_RGB565:
 435                return 10;
 436        case DRM_FORMAT_XRGB8888:
 437        case DRM_FORMAT_XBGR8888:
 438        case DRM_FORMAT_ARGB8888:
 439        case DRM_FORMAT_ABGR8888:
 440        case DRM_FORMAT_XRGB2101010:
 441        case DRM_FORMAT_XBGR2101010:
 442        case DRM_FORMAT_ARGB2101010:
 443        case DRM_FORMAT_ABGR2101010:
 444        case DRM_FORMAT_XVYU2101010:
 445        case DRM_FORMAT_Y212:
 446        case DRM_FORMAT_Y216:
 447                return 6;
 448        case DRM_FORMAT_NV12:
 449                return 20;
 450        case DRM_FORMAT_P010:
 451        case DRM_FORMAT_P012:
 452        case DRM_FORMAT_P016:
 453                return 12;
 454        case DRM_FORMAT_XRGB16161616F:
 455        case DRM_FORMAT_XBGR16161616F:
 456        case DRM_FORMAT_ARGB16161616F:
 457        case DRM_FORMAT_ABGR16161616F:
 458        case DRM_FORMAT_XVYU12_16161616:
 459        case DRM_FORMAT_XVYU16161616:
 460                return 4;
 461        default:
 462                return 1;
 463        }
 464}
 465
 466static int icl_plane_max_width(const struct drm_framebuffer *fb,
 467                               int color_plane,
 468                               unsigned int rotation)
 469{
 470        return 5120;
 471}
 472
 473static int skl_plane_max_height(const struct drm_framebuffer *fb,
 474                                int color_plane,
 475                                unsigned int rotation)
 476{
 477        return 4096;
 478}
 479
 480static int icl_plane_max_height(const struct drm_framebuffer *fb,
 481                                int color_plane,
 482                                unsigned int rotation)
 483{
 484        return 4320;
 485}
 486
 487static unsigned int
 488skl_plane_max_stride(struct intel_plane *plane,
 489                     u32 pixel_format, u64 modifier,
 490                     unsigned int rotation)
 491{
 492        struct drm_i915_private *i915 = to_i915(plane->base.dev);
 493        const struct drm_format_info *info = drm_format_info(pixel_format);
 494        int cpp = info->cpp[0];
 495        int max_horizontal_pixels = 8192;
 496        int max_stride_bytes;
 497
 498        if (DISPLAY_VER(i915) >= 13) {
 499                /*
 500                 * The stride in bytes must not exceed of the size
 501                 * of 128K bytes. For pixel formats of 64bpp will allow
 502                 * for a 16K pixel surface.
 503                 */
 504                max_stride_bytes = 131072;
 505                if (cpp == 8)
 506                        max_horizontal_pixels = 16384;
 507                else
 508                        max_horizontal_pixels = 65536;
 509        } else {
 510                /*
 511                 * "The stride in bytes must not exceed the
 512                 * of the size of 8K pixels and 32K bytes."
 513                 */
 514                max_stride_bytes = 32768;
 515        }
 516
 517        if (drm_rotation_90_or_270(rotation))
 518                return min(max_horizontal_pixels, max_stride_bytes / cpp);
 519        else
 520                return min(max_horizontal_pixels * cpp, max_stride_bytes);
 521}
 522
 523
 524/* Preoffset values for YUV to RGB Conversion */
 525#define PREOFF_YUV_TO_RGB_HI            0x1800
 526#define PREOFF_YUV_TO_RGB_ME            0x0000
 527#define PREOFF_YUV_TO_RGB_LO            0x1800
 528
 529#define  ROFF(x)          (((x) & 0xffff) << 16)
 530#define  GOFF(x)          (((x) & 0xffff) << 0)
 531#define  BOFF(x)          (((x) & 0xffff) << 16)
 532
 533/*
 534 * Programs the input color space conversion stage for ICL HDR planes.
 535 * Note that it is assumed that this stage always happens after YUV
 536 * range correction. Thus, the input to this stage is assumed to be
 537 * in full-range YCbCr.
 538 */
 539static void
 540icl_program_input_csc(struct intel_plane *plane,
 541                      const struct intel_crtc_state *crtc_state,
 542                      const struct intel_plane_state *plane_state)
 543{
 544        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 545        enum pipe pipe = plane->pipe;
 546        enum plane_id plane_id = plane->id;
 547
 548        static const u16 input_csc_matrix[][9] = {
 549                /*
 550                 * BT.601 full range YCbCr -> full range RGB
 551                 * The matrix required is :
 552                 * [1.000, 0.000, 1.371,
 553                 *  1.000, -0.336, -0.698,
 554                 *  1.000, 1.732, 0.0000]
 555                 */
 556                [DRM_COLOR_YCBCR_BT601] = {
 557                        0x7AF8, 0x7800, 0x0,
 558                        0x8B28, 0x7800, 0x9AC0,
 559                        0x0, 0x7800, 0x7DD8,
 560                },
 561                /*
 562                 * BT.709 full range YCbCr -> full range RGB
 563                 * The matrix required is :
 564                 * [1.000, 0.000, 1.574,
 565                 *  1.000, -0.187, -0.468,
 566                 *  1.000, 1.855, 0.0000]
 567                 */
 568                [DRM_COLOR_YCBCR_BT709] = {
 569                        0x7C98, 0x7800, 0x0,
 570                        0x9EF8, 0x7800, 0xAC00,
 571                        0x0, 0x7800,  0x7ED8,
 572                },
 573                /*
 574                 * BT.2020 full range YCbCr -> full range RGB
 575                 * The matrix required is :
 576                 * [1.000, 0.000, 1.474,
 577                 *  1.000, -0.1645, -0.5713,
 578                 *  1.000, 1.8814, 0.0000]
 579                 */
 580                [DRM_COLOR_YCBCR_BT2020] = {
 581                        0x7BC8, 0x7800, 0x0,
 582                        0x8928, 0x7800, 0xAA88,
 583                        0x0, 0x7800, 0x7F10,
 584                },
 585        };
 586        const u16 *csc = input_csc_matrix[plane_state->hw.color_encoding];
 587
 588        intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 0),
 589                          ROFF(csc[0]) | GOFF(csc[1]));
 590        intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 1),
 591                          BOFF(csc[2]));
 592        intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 2),
 593                          ROFF(csc[3]) | GOFF(csc[4]));
 594        intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 3),
 595                          BOFF(csc[5]));
 596        intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 4),
 597                          ROFF(csc[6]) | GOFF(csc[7]));
 598        intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 5),
 599                          BOFF(csc[8]));
 600
 601        intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 0),
 602                          PREOFF_YUV_TO_RGB_HI);
 603        intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1),
 604                          PREOFF_YUV_TO_RGB_ME);
 605        intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 2),
 606                          PREOFF_YUV_TO_RGB_LO);
 607        intel_de_write_fw(dev_priv,
 608                          PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 0), 0x0);
 609        intel_de_write_fw(dev_priv,
 610                          PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 1), 0x0);
 611        intel_de_write_fw(dev_priv,
 612                          PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 2), 0x0);
 613}
 614
 615static unsigned int skl_plane_stride_mult(const struct drm_framebuffer *fb,
 616                                          int color_plane, unsigned int rotation)
 617{
 618        /*
 619         * The stride is either expressed as a multiple of 64 bytes chunks for
 620         * linear buffers or in number of tiles for tiled buffers.
 621         */
 622        if (is_surface_linear(fb, color_plane))
 623                return 64;
 624        else if (drm_rotation_90_or_270(rotation))
 625                return intel_tile_height(fb, color_plane);
 626        else
 627                return intel_tile_width_bytes(fb, color_plane);
 628}
 629
 630static u32 skl_plane_stride(const struct intel_plane_state *plane_state,
 631                            int color_plane)
 632{
 633        const struct drm_framebuffer *fb = plane_state->hw.fb;
 634        unsigned int rotation = plane_state->hw.rotation;
 635        u32 stride = plane_state->view.color_plane[color_plane].stride;
 636
 637        if (color_plane >= fb->format->num_planes)
 638                return 0;
 639
 640        return stride / skl_plane_stride_mult(fb, color_plane, rotation);
 641}
 642
 643static void
 644skl_disable_plane(struct intel_plane *plane,
 645                  const struct intel_crtc_state *crtc_state)
 646{
 647        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 648        enum plane_id plane_id = plane->id;
 649        enum pipe pipe = plane->pipe;
 650        unsigned long irqflags;
 651
 652        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 653
 654        if (icl_is_hdr_plane(dev_priv, plane_id))
 655                intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id), 0);
 656
 657        skl_write_plane_wm(plane, crtc_state);
 658
 659        intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), 0);
 660        intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), 0);
 661
 662        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 663}
 664
 665static bool
 666skl_plane_get_hw_state(struct intel_plane *plane,
 667                       enum pipe *pipe)
 668{
 669        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 670        enum intel_display_power_domain power_domain;
 671        enum plane_id plane_id = plane->id;
 672        intel_wakeref_t wakeref;
 673        bool ret;
 674
 675        power_domain = POWER_DOMAIN_PIPE(plane->pipe);
 676        wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
 677        if (!wakeref)
 678                return false;
 679
 680        ret = intel_de_read(dev_priv, PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;
 681
 682        *pipe = plane->pipe;
 683
 684        intel_display_power_put(dev_priv, power_domain, wakeref);
 685
 686        return ret;
 687}
 688
 689static u32 skl_plane_ctl_format(u32 pixel_format)
 690{
 691        switch (pixel_format) {
 692        case DRM_FORMAT_C8:
 693                return PLANE_CTL_FORMAT_INDEXED;
 694        case DRM_FORMAT_RGB565:
 695                return PLANE_CTL_FORMAT_RGB_565;
 696        case DRM_FORMAT_XBGR8888:
 697        case DRM_FORMAT_ABGR8888:
 698                return PLANE_CTL_FORMAT_XRGB_8888 | PLANE_CTL_ORDER_RGBX;
 699        case DRM_FORMAT_XRGB8888:
 700        case DRM_FORMAT_ARGB8888:
 701                return PLANE_CTL_FORMAT_XRGB_8888;
 702        case DRM_FORMAT_XBGR2101010:
 703        case DRM_FORMAT_ABGR2101010:
 704                return PLANE_CTL_FORMAT_XRGB_2101010 | PLANE_CTL_ORDER_RGBX;
 705        case DRM_FORMAT_XRGB2101010:
 706        case DRM_FORMAT_ARGB2101010:
 707                return PLANE_CTL_FORMAT_XRGB_2101010;
 708        case DRM_FORMAT_XBGR16161616F:
 709        case DRM_FORMAT_ABGR16161616F:
 710                return PLANE_CTL_FORMAT_XRGB_16161616F | PLANE_CTL_ORDER_RGBX;
 711        case DRM_FORMAT_XRGB16161616F:
 712        case DRM_FORMAT_ARGB16161616F:
 713                return PLANE_CTL_FORMAT_XRGB_16161616F;
 714        case DRM_FORMAT_XYUV8888:
 715                return PLANE_CTL_FORMAT_XYUV;
 716        case DRM_FORMAT_YUYV:
 717                return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_YUYV;
 718        case DRM_FORMAT_YVYU:
 719                return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_YVYU;
 720        case DRM_FORMAT_UYVY:
 721                return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_UYVY;
 722        case DRM_FORMAT_VYUY:
 723                return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_VYUY;
 724        case DRM_FORMAT_NV12:
 725                return PLANE_CTL_FORMAT_NV12;
 726        case DRM_FORMAT_P010:
 727                return PLANE_CTL_FORMAT_P010;
 728        case DRM_FORMAT_P012:
 729                return PLANE_CTL_FORMAT_P012;
 730        case DRM_FORMAT_P016:
 731                return PLANE_CTL_FORMAT_P016;
 732        case DRM_FORMAT_Y210:
 733                return PLANE_CTL_FORMAT_Y210;
 734        case DRM_FORMAT_Y212:
 735                return PLANE_CTL_FORMAT_Y212;
 736        case DRM_FORMAT_Y216:
 737                return PLANE_CTL_FORMAT_Y216;
 738        case DRM_FORMAT_XVYU2101010:
 739                return PLANE_CTL_FORMAT_Y410;
 740        case DRM_FORMAT_XVYU12_16161616:
 741                return PLANE_CTL_FORMAT_Y412;
 742        case DRM_FORMAT_XVYU16161616:
 743                return PLANE_CTL_FORMAT_Y416;
 744        default:
 745                MISSING_CASE(pixel_format);
 746        }
 747
 748        return 0;
 749}
 750
 751static u32 skl_plane_ctl_alpha(const struct intel_plane_state *plane_state)
 752{
 753        if (!plane_state->hw.fb->format->has_alpha)
 754                return PLANE_CTL_ALPHA_DISABLE;
 755
 756        switch (plane_state->hw.pixel_blend_mode) {
 757        case DRM_MODE_BLEND_PIXEL_NONE:
 758                return PLANE_CTL_ALPHA_DISABLE;
 759        case DRM_MODE_BLEND_PREMULTI:
 760                return PLANE_CTL_ALPHA_SW_PREMULTIPLY;
 761        case DRM_MODE_BLEND_COVERAGE:
 762                return PLANE_CTL_ALPHA_HW_PREMULTIPLY;
 763        default:
 764                MISSING_CASE(plane_state->hw.pixel_blend_mode);
 765                return PLANE_CTL_ALPHA_DISABLE;
 766        }
 767}
 768
 769static u32 glk_plane_color_ctl_alpha(const struct intel_plane_state *plane_state)
 770{
 771        if (!plane_state->hw.fb->format->has_alpha)
 772                return PLANE_COLOR_ALPHA_DISABLE;
 773
 774        switch (plane_state->hw.pixel_blend_mode) {
 775        case DRM_MODE_BLEND_PIXEL_NONE:
 776                return PLANE_COLOR_ALPHA_DISABLE;
 777        case DRM_MODE_BLEND_PREMULTI:
 778                return PLANE_COLOR_ALPHA_SW_PREMULTIPLY;
 779        case DRM_MODE_BLEND_COVERAGE:
 780                return PLANE_COLOR_ALPHA_HW_PREMULTIPLY;
 781        default:
 782                MISSING_CASE(plane_state->hw.pixel_blend_mode);
 783                return PLANE_COLOR_ALPHA_DISABLE;
 784        }
 785}
 786
 787static u32 skl_plane_ctl_tiling(u64 fb_modifier)
 788{
 789        switch (fb_modifier) {
 790        case DRM_FORMAT_MOD_LINEAR:
 791                break;
 792        case I915_FORMAT_MOD_X_TILED:
 793                return PLANE_CTL_TILED_X;
 794        case I915_FORMAT_MOD_Y_TILED:
 795                return PLANE_CTL_TILED_Y;
 796        case I915_FORMAT_MOD_Y_TILED_CCS:
 797        case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
 798                return PLANE_CTL_TILED_Y | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
 799        case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
 800                return PLANE_CTL_TILED_Y |
 801                       PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
 802                       PLANE_CTL_CLEAR_COLOR_DISABLE;
 803        case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
 804                return PLANE_CTL_TILED_Y | PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE;
 805        case I915_FORMAT_MOD_Yf_TILED:
 806                return PLANE_CTL_TILED_YF;
 807        case I915_FORMAT_MOD_Yf_TILED_CCS:
 808                return PLANE_CTL_TILED_YF | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
 809        default:
 810                MISSING_CASE(fb_modifier);
 811        }
 812
 813        return 0;
 814}
 815
 816static u32 skl_plane_ctl_rotate(unsigned int rotate)
 817{
 818        switch (rotate) {
 819        case DRM_MODE_ROTATE_0:
 820                break;
 821        /*
 822         * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr
 823         * while i915 HW rotation is clockwise, thats why this swapping.
 824         */
 825        case DRM_MODE_ROTATE_90:
 826                return PLANE_CTL_ROTATE_270;
 827        case DRM_MODE_ROTATE_180:
 828                return PLANE_CTL_ROTATE_180;
 829        case DRM_MODE_ROTATE_270:
 830                return PLANE_CTL_ROTATE_90;
 831        default:
 832                MISSING_CASE(rotate);
 833        }
 834
 835        return 0;
 836}
 837
 838static u32 icl_plane_ctl_flip(unsigned int reflect)
 839{
 840        switch (reflect) {
 841        case 0:
 842                break;
 843        case DRM_MODE_REFLECT_X:
 844                return PLANE_CTL_FLIP_HORIZONTAL;
 845        case DRM_MODE_REFLECT_Y:
 846        default:
 847                MISSING_CASE(reflect);
 848        }
 849
 850        return 0;
 851}
 852
 853static u32 adlp_plane_ctl_arb_slots(const struct intel_plane_state *plane_state)
 854{
 855        const struct drm_framebuffer *fb = plane_state->hw.fb;
 856
 857        if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) {
 858                switch (fb->format->cpp[0]) {
 859                case 2:
 860                        return PLANE_CTL_ARB_SLOTS(1);
 861                default:
 862                        return PLANE_CTL_ARB_SLOTS(0);
 863                }
 864        } else {
 865                switch (fb->format->cpp[0]) {
 866                case 8:
 867                        return PLANE_CTL_ARB_SLOTS(3);
 868                case 4:
 869                        return PLANE_CTL_ARB_SLOTS(1);
 870                default:
 871                        return PLANE_CTL_ARB_SLOTS(0);
 872                }
 873        }
 874}
 875
 876static u32 skl_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
 877{
 878        struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
 879        u32 plane_ctl = 0;
 880
 881        if (DISPLAY_VER(dev_priv) >= 10)
 882                return plane_ctl;
 883
 884        if (crtc_state->gamma_enable)
 885                plane_ctl |= PLANE_CTL_PIPE_GAMMA_ENABLE;
 886
 887        if (crtc_state->csc_enable)
 888                plane_ctl |= PLANE_CTL_PIPE_CSC_ENABLE;
 889
 890        return plane_ctl;
 891}
 892
 893static u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state,
 894                         const struct intel_plane_state *plane_state)
 895{
 896        struct drm_i915_private *dev_priv =
 897                to_i915(plane_state->uapi.plane->dev);
 898        const struct drm_framebuffer *fb = plane_state->hw.fb;
 899        unsigned int rotation = plane_state->hw.rotation;
 900        const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
 901        u32 plane_ctl;
 902
 903        plane_ctl = PLANE_CTL_ENABLE;
 904
 905        if (DISPLAY_VER(dev_priv) < 10) {
 906                plane_ctl |= skl_plane_ctl_alpha(plane_state);
 907                plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE;
 908
 909                if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
 910                        plane_ctl |= PLANE_CTL_YUV_TO_RGB_CSC_FORMAT_BT709;
 911
 912                if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
 913                        plane_ctl |= PLANE_CTL_YUV_RANGE_CORRECTION_DISABLE;
 914        }
 915
 916        plane_ctl |= skl_plane_ctl_format(fb->format->format);
 917        plane_ctl |= skl_plane_ctl_tiling(fb->modifier);
 918        plane_ctl |= skl_plane_ctl_rotate(rotation & DRM_MODE_ROTATE_MASK);
 919
 920        if (DISPLAY_VER(dev_priv) >= 11)
 921                plane_ctl |= icl_plane_ctl_flip(rotation &
 922                                                DRM_MODE_REFLECT_MASK);
 923
 924        if (key->flags & I915_SET_COLORKEY_DESTINATION)
 925                plane_ctl |= PLANE_CTL_KEY_ENABLE_DESTINATION;
 926        else if (key->flags & I915_SET_COLORKEY_SOURCE)
 927                plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE;
 928
 929        /* Wa_22012358565:adl-p */
 930        if (DISPLAY_VER(dev_priv) == 13)
 931                plane_ctl |= adlp_plane_ctl_arb_slots(plane_state);
 932
 933        return plane_ctl;
 934}
 935
 936static u32 glk_plane_color_ctl_crtc(const struct intel_crtc_state *crtc_state)
 937{
 938        struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
 939        u32 plane_color_ctl = 0;
 940
 941        if (DISPLAY_VER(dev_priv) >= 11)
 942                return plane_color_ctl;
 943
 944        if (crtc_state->gamma_enable)
 945                plane_color_ctl |= PLANE_COLOR_PIPE_GAMMA_ENABLE;
 946
 947        if (crtc_state->csc_enable)
 948                plane_color_ctl |= PLANE_COLOR_PIPE_CSC_ENABLE;
 949
 950        return plane_color_ctl;
 951}
 952
 953static u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state,
 954                               const struct intel_plane_state *plane_state)
 955{
 956        struct drm_i915_private *dev_priv =
 957                to_i915(plane_state->uapi.plane->dev);
 958        const struct drm_framebuffer *fb = plane_state->hw.fb;
 959        struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
 960        u32 plane_color_ctl = 0;
 961
 962        plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE;
 963        plane_color_ctl |= glk_plane_color_ctl_alpha(plane_state);
 964
 965        if (fb->format->is_yuv && !icl_is_hdr_plane(dev_priv, plane->id)) {
 966                switch (plane_state->hw.color_encoding) {
 967                case DRM_COLOR_YCBCR_BT709:
 968                        plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709;
 969                        break;
 970                case DRM_COLOR_YCBCR_BT2020:
 971                        plane_color_ctl |=
 972                                PLANE_COLOR_CSC_MODE_YUV2020_TO_RGB2020;
 973                        break;
 974                default:
 975                        plane_color_ctl |=
 976                                PLANE_COLOR_CSC_MODE_YUV601_TO_RGB601;
 977                }
 978                if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
 979                        plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE;
 980        } else if (fb->format->is_yuv) {
 981                plane_color_ctl |= PLANE_COLOR_INPUT_CSC_ENABLE;
 982                if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
 983                        plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE;
 984        }
 985
 986        return plane_color_ctl;
 987}
 988
 989static u32 skl_surf_address(const struct intel_plane_state *plane_state,
 990                            int color_plane)
 991{
 992        const struct drm_framebuffer *fb = plane_state->hw.fb;
 993        u32 offset = plane_state->view.color_plane[color_plane].offset;
 994
 995        if (intel_fb_uses_dpt(fb)) {
 996                WARN_ON(offset & 0x1fffff);
 997                return offset >> 9;
 998        } else {
 999                WARN_ON(offset & 0xfff);
1000                return offset;
1001        }
1002}
1003
1004static void
1005skl_program_plane(struct intel_plane *plane,
1006                  const struct intel_crtc_state *crtc_state,
1007                  const struct intel_plane_state *plane_state,
1008                  int color_plane)
1009{
1010        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1011        enum plane_id plane_id = plane->id;
1012        enum pipe pipe = plane->pipe;
1013        const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1014        u32 surf_addr = skl_surf_address(plane_state, color_plane);
1015        u32 stride = skl_plane_stride(plane_state, color_plane);
1016        const struct drm_framebuffer *fb = plane_state->hw.fb;
1017        int aux_plane = skl_main_to_aux_plane(fb, color_plane);
1018        int crtc_x = plane_state->uapi.dst.x1;
1019        int crtc_y = plane_state->uapi.dst.y1;
1020        u32 x = plane_state->view.color_plane[color_plane].x;
1021        u32 y = plane_state->view.color_plane[color_plane].y;
1022        u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1023        u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1024        u8 alpha = plane_state->hw.alpha >> 8;
1025        u32 plane_color_ctl = 0, aux_dist = 0;
1026        unsigned long irqflags;
1027        u32 keymsk, keymax;
1028        u32 plane_ctl = plane_state->ctl;
1029
1030        plane_ctl |= skl_plane_ctl_crtc(crtc_state);
1031
1032        if (DISPLAY_VER(dev_priv) >= 10)
1033                plane_color_ctl = plane_state->color_ctl |
1034                        glk_plane_color_ctl_crtc(crtc_state);
1035
1036        /* Sizes are 0 based */
1037        src_w--;
1038        src_h--;
1039
1040        keymax = (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha);
1041
1042        keymsk = key->channel_mask & 0x7ffffff;
1043        if (alpha < 0xff)
1044                keymsk |= PLANE_KEYMSK_ALPHA_ENABLE;
1045
1046        /* The scaler will handle the output position */
1047        if (plane_state->scaler_id >= 0) {
1048                crtc_x = 0;
1049                crtc_y = 0;
1050        }
1051
1052        if (aux_plane) {
1053                aux_dist = skl_surf_address(plane_state, aux_plane) - surf_addr;
1054
1055                if (DISPLAY_VER(dev_priv) < 12)
1056                        aux_dist |= skl_plane_stride(plane_state, aux_plane);
1057        }
1058
1059        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1060
1061        intel_de_write_fw(dev_priv, PLANE_STRIDE(pipe, plane_id), stride);
1062        intel_de_write_fw(dev_priv, PLANE_POS(pipe, plane_id),
1063                          (crtc_y << 16) | crtc_x);
1064        intel_de_write_fw(dev_priv, PLANE_SIZE(pipe, plane_id),
1065                          (src_h << 16) | src_w);
1066
1067        intel_de_write_fw(dev_priv, PLANE_AUX_DIST(pipe, plane_id), aux_dist);
1068
1069        if (icl_is_hdr_plane(dev_priv, plane_id))
1070                intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id),
1071                                  plane_state->cus_ctl);
1072
1073        if (DISPLAY_VER(dev_priv) >= 10)
1074                intel_de_write_fw(dev_priv, PLANE_COLOR_CTL(pipe, plane_id),
1075                                  plane_color_ctl);
1076
1077        if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id))
1078                icl_program_input_csc(plane, crtc_state, plane_state);
1079
1080        if (fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC)
1081                intel_uncore_write64_fw(&dev_priv->uncore,
1082                                        PLANE_CC_VAL(pipe, plane_id), plane_state->ccval);
1083
1084        skl_write_plane_wm(plane, crtc_state);
1085
1086        intel_de_write_fw(dev_priv, PLANE_KEYVAL(pipe, plane_id),
1087                          key->min_value);
1088        intel_de_write_fw(dev_priv, PLANE_KEYMSK(pipe, plane_id), keymsk);
1089        intel_de_write_fw(dev_priv, PLANE_KEYMAX(pipe, plane_id), keymax);
1090
1091        intel_de_write_fw(dev_priv, PLANE_OFFSET(pipe, plane_id),
1092                          (y << 16) | x);
1093
1094        if (DISPLAY_VER(dev_priv) < 11)
1095                intel_de_write_fw(dev_priv, PLANE_AUX_OFFSET(pipe, plane_id),
1096                                  (plane_state->view.color_plane[1].y << 16) |
1097                                   plane_state->view.color_plane[1].x);
1098
1099        if (!drm_atomic_crtc_needs_modeset(&crtc_state->uapi))
1100                intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, color_plane);
1101
1102        /*
1103         * Enable the scaler before the plane so that we don't
1104         * get a catastrophic underrun even if the two operations
1105         * end up happening in two different frames.
1106         */
1107        if (plane_state->scaler_id >= 0)
1108                skl_program_plane_scaler(plane, crtc_state, plane_state);
1109
1110        /*
1111         * The control register self-arms if the plane was previously
1112         * disabled. Try to make the plane enable atomic by writing
1113         * the control register just before the surface register.
1114         */
1115        intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
1116        intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
1117                          intel_plane_ggtt_offset(plane_state) + surf_addr);
1118
1119        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1120}
1121
1122static void
1123skl_plane_async_flip(struct intel_plane *plane,
1124                     const struct intel_crtc_state *crtc_state,
1125                     const struct intel_plane_state *plane_state,
1126                     bool async_flip)
1127{
1128        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1129        unsigned long irqflags;
1130        enum plane_id plane_id = plane->id;
1131        enum pipe pipe = plane->pipe;
1132        u32 surf_addr = plane_state->view.color_plane[0].offset;
1133        u32 plane_ctl = plane_state->ctl;
1134
1135        plane_ctl |= skl_plane_ctl_crtc(crtc_state);
1136
1137        if (async_flip)
1138                plane_ctl |= PLANE_CTL_ASYNC_FLIP;
1139
1140        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1141
1142        intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
1143        intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
1144                          intel_plane_ggtt_offset(plane_state) + surf_addr);
1145
1146        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1147}
1148
1149static void
1150skl_update_plane(struct intel_plane *plane,
1151                 const struct intel_crtc_state *crtc_state,
1152                 const struct intel_plane_state *plane_state)
1153{
1154        int color_plane = 0;
1155
1156        if (plane_state->planar_linked_plane && !plane_state->planar_slave)
1157                /* Program the UV plane on planar master */
1158                color_plane = 1;
1159
1160        skl_program_plane(plane, crtc_state, plane_state, color_plane);
1161}
1162
1163static bool intel_format_is_p01x(u32 format)
1164{
1165        switch (format) {
1166        case DRM_FORMAT_P010:
1167        case DRM_FORMAT_P012:
1168        case DRM_FORMAT_P016:
1169                return true;
1170        default:
1171                return false;
1172        }
1173}
1174
1175static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
1176                              const struct intel_plane_state *plane_state)
1177{
1178        struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1179        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1180        const struct drm_framebuffer *fb = plane_state->hw.fb;
1181        unsigned int rotation = plane_state->hw.rotation;
1182
1183        if (!fb)
1184                return 0;
1185
1186        if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) &&
1187            is_ccs_modifier(fb->modifier)) {
1188                drm_dbg_kms(&dev_priv->drm,
1189                            "RC support only with 0/180 degree rotation (%x)\n",
1190                            rotation);
1191                return -EINVAL;
1192        }
1193
1194        if (rotation & DRM_MODE_REFLECT_X &&
1195            fb->modifier == DRM_FORMAT_MOD_LINEAR) {
1196                drm_dbg_kms(&dev_priv->drm,
1197                            "horizontal flip is not supported with linear surface formats\n");
1198                return -EINVAL;
1199        }
1200
1201        if (drm_rotation_90_or_270(rotation)) {
1202                if (!intel_fb_supports_90_270_rotation(to_intel_framebuffer(fb))) {
1203                        drm_dbg_kms(&dev_priv->drm,
1204                                    "Y/Yf tiling required for 90/270!\n");
1205                        return -EINVAL;
1206                }
1207
1208                /*
1209                 * 90/270 is not allowed with RGB64 16:16:16:16 and
1210                 * Indexed 8-bit. RGB 16-bit 5:6:5 is allowed gen11 onwards.
1211                 */
1212                switch (fb->format->format) {
1213                case DRM_FORMAT_RGB565:
1214                        if (DISPLAY_VER(dev_priv) >= 11)
1215                                break;
1216                        fallthrough;
1217                case DRM_FORMAT_C8:
1218                case DRM_FORMAT_XRGB16161616F:
1219                case DRM_FORMAT_XBGR16161616F:
1220                case DRM_FORMAT_ARGB16161616F:
1221                case DRM_FORMAT_ABGR16161616F:
1222                case DRM_FORMAT_Y210:
1223                case DRM_FORMAT_Y212:
1224                case DRM_FORMAT_Y216:
1225                case DRM_FORMAT_XVYU12_16161616:
1226                case DRM_FORMAT_XVYU16161616:
1227                        drm_dbg_kms(&dev_priv->drm,
1228                                    "Unsupported pixel format %p4cc for 90/270!\n",
1229                                    &fb->format->format);
1230                        return -EINVAL;
1231                default:
1232                        break;
1233                }
1234        }
1235
1236        /* Y-tiling is not supported in IF-ID Interlace mode */
1237        if (crtc_state->hw.enable &&
1238            crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE &&
1239            (fb->modifier == I915_FORMAT_MOD_Y_TILED ||
1240             fb->modifier == I915_FORMAT_MOD_Yf_TILED ||
1241             fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
1242             fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS ||
1243             fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS ||
1244             fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS ||
1245             fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC)) {
1246                drm_dbg_kms(&dev_priv->drm,
1247                            "Y/Yf tiling not supported in IF-ID mode\n");
1248                return -EINVAL;
1249        }
1250
1251        /* Wa_1606054188:tgl,adl-s */
1252        if ((IS_ALDERLAKE_S(dev_priv) || IS_TIGERLAKE(dev_priv)) &&
1253            plane_state->ckey.flags & I915_SET_COLORKEY_SOURCE &&
1254            intel_format_is_p01x(fb->format->format)) {
1255                drm_dbg_kms(&dev_priv->drm,
1256                            "Source color keying not supported with P01x formats\n");
1257                return -EINVAL;
1258        }
1259
1260        return 0;
1261}
1262
1263static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_state,
1264                                           const struct intel_plane_state *plane_state)
1265{
1266        struct drm_i915_private *dev_priv =
1267                to_i915(plane_state->uapi.plane->dev);
1268        int crtc_x = plane_state->uapi.dst.x1;
1269        int crtc_w = drm_rect_width(&plane_state->uapi.dst);
1270        int pipe_src_w = crtc_state->pipe_src_w;
1271
1272        /*
1273         * Display WA #1175: glk
1274         * Planes other than the cursor may cause FIFO underflow and display
1275         * corruption if starting less than 4 pixels from the right edge of
1276         * the screen.
1277         * Besides the above WA fix the similar problem, where planes other
1278         * than the cursor ending less than 4 pixels from the left edge of the
1279         * screen may cause FIFO underflow and display corruption.
1280         */
1281        if (DISPLAY_VER(dev_priv) == 10 &&
1282            (crtc_x + crtc_w < 4 || crtc_x > pipe_src_w - 4)) {
1283                drm_dbg_kms(&dev_priv->drm,
1284                            "requested plane X %s position %d invalid (valid range %d-%d)\n",
1285                            crtc_x + crtc_w < 4 ? "end" : "start",
1286                            crtc_x + crtc_w < 4 ? crtc_x + crtc_w : crtc_x,
1287                            4, pipe_src_w - 4);
1288                return -ERANGE;
1289        }
1290
1291        return 0;
1292}
1293
1294static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_state)
1295{
1296        const struct drm_framebuffer *fb = plane_state->hw.fb;
1297        unsigned int rotation = plane_state->hw.rotation;
1298        int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1299
1300        /* Display WA #1106 */
1301        if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
1302            src_w & 3 &&
1303            (rotation == DRM_MODE_ROTATE_270 ||
1304             rotation == (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90))) {
1305                DRM_DEBUG_KMS("src width must be multiple of 4 for rotated planar YUV\n");
1306                return -EINVAL;
1307        }
1308
1309        return 0;
1310}
1311
1312static int skl_plane_max_scale(struct drm_i915_private *dev_priv,
1313                               const struct drm_framebuffer *fb)
1314{
1315        /*
1316         * We don't yet know the final source width nor
1317         * whether we can use the HQ scaler mode. Assume
1318         * the best case.
1319         * FIXME need to properly check this later.
1320         */
1321        if (DISPLAY_VER(dev_priv) >= 10 ||
1322            !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
1323                return 0x30000 - 1;
1324        else
1325                return 0x20000 - 1;
1326}
1327
1328static int intel_plane_min_width(struct intel_plane *plane,
1329                                 const struct drm_framebuffer *fb,
1330                                 int color_plane,
1331                                 unsigned int rotation)
1332{
1333        if (plane->min_width)
1334                return plane->min_width(fb, color_plane, rotation);
1335        else
1336                return 1;
1337}
1338
1339static int intel_plane_max_width(struct intel_plane *plane,
1340                                 const struct drm_framebuffer *fb,
1341                                 int color_plane,
1342                                 unsigned int rotation)
1343{
1344        if (plane->max_width)
1345                return plane->max_width(fb, color_plane, rotation);
1346        else
1347                return INT_MAX;
1348}
1349
1350static int intel_plane_max_height(struct intel_plane *plane,
1351                                  const struct drm_framebuffer *fb,
1352                                  int color_plane,
1353                                  unsigned int rotation)
1354{
1355        if (plane->max_height)
1356                return plane->max_height(fb, color_plane, rotation);
1357        else
1358                return INT_MAX;
1359}
1360
1361static bool
1362skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state,
1363                               int main_x, int main_y, u32 main_offset,
1364                               int ccs_plane)
1365{
1366        const struct drm_framebuffer *fb = plane_state->hw.fb;
1367        int aux_x = plane_state->view.color_plane[ccs_plane].x;
1368        int aux_y = plane_state->view.color_plane[ccs_plane].y;
1369        u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset;
1370        u32 alignment = intel_surf_alignment(fb, ccs_plane);
1371        int hsub;
1372        int vsub;
1373
1374        intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane);
1375        while (aux_offset >= main_offset && aux_y <= main_y) {
1376                int x, y;
1377
1378                if (aux_x == main_x && aux_y == main_y)
1379                        break;
1380
1381                if (aux_offset == 0)
1382                        break;
1383
1384                x = aux_x / hsub;
1385                y = aux_y / vsub;
1386                aux_offset = intel_plane_adjust_aligned_offset(&x, &y,
1387                                                               plane_state,
1388                                                               ccs_plane,
1389                                                               aux_offset,
1390                                                               aux_offset -
1391                                                                alignment);
1392                aux_x = x * hsub + aux_x % hsub;
1393                aux_y = y * vsub + aux_y % vsub;
1394        }
1395
1396        if (aux_x != main_x || aux_y != main_y)
1397                return false;
1398
1399        plane_state->view.color_plane[ccs_plane].offset = aux_offset;
1400        plane_state->view.color_plane[ccs_plane].x = aux_x;
1401        plane_state->view.color_plane[ccs_plane].y = aux_y;
1402
1403        return true;
1404}
1405
1406
1407int skl_calc_main_surface_offset(const struct intel_plane_state *plane_state,
1408                                 int *x, int *y, u32 *offset)
1409{
1410        struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1411        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1412        const struct drm_framebuffer *fb = plane_state->hw.fb;
1413        const int aux_plane = skl_main_to_aux_plane(fb, 0);
1414        const u32 aux_offset = plane_state->view.color_plane[aux_plane].offset;
1415        const u32 alignment = intel_surf_alignment(fb, 0);
1416        const int w = drm_rect_width(&plane_state->uapi.src) >> 16;
1417
1418        intel_add_fb_offsets(x, y, plane_state, 0);
1419        *offset = intel_plane_compute_aligned_offset(x, y, plane_state, 0);
1420        if (drm_WARN_ON(&dev_priv->drm, alignment && !is_power_of_2(alignment)))
1421                return -EINVAL;
1422
1423        /*
1424         * AUX surface offset is specified as the distance from the
1425         * main surface offset, and it must be non-negative. Make
1426         * sure that is what we will get.
1427         */
1428        if (aux_plane && *offset > aux_offset)
1429                *offset = intel_plane_adjust_aligned_offset(x, y, plane_state, 0,
1430                                                            *offset,
1431                                                            aux_offset & ~(alignment - 1));
1432
1433        /*
1434         * When using an X-tiled surface, the plane blows up
1435         * if the x offset + width exceed the stride.
1436         *
1437         * TODO: linear and Y-tiled seem fine, Yf untested,
1438         */
1439        if (fb->modifier == I915_FORMAT_MOD_X_TILED) {
1440                int cpp = fb->format->cpp[0];
1441
1442                while ((*x + w) * cpp > plane_state->view.color_plane[0].stride) {
1443                        if (*offset == 0) {
1444                                drm_dbg_kms(&dev_priv->drm,
1445                                            "Unable to find suitable display surface offset due to X-tiling\n");
1446                                return -EINVAL;
1447                        }
1448
1449                        *offset = intel_plane_adjust_aligned_offset(x, y, plane_state, 0,
1450                                                                    *offset,
1451                                                                    *offset - alignment);
1452                }
1453        }
1454
1455        return 0;
1456}
1457
1458static int skl_check_main_surface(struct intel_plane_state *plane_state)
1459{
1460        struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1461        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1462        const struct drm_framebuffer *fb = plane_state->hw.fb;
1463        const unsigned int rotation = plane_state->hw.rotation;
1464        int x = plane_state->uapi.src.x1 >> 16;
1465        int y = plane_state->uapi.src.y1 >> 16;
1466        const int w = drm_rect_width(&plane_state->uapi.src) >> 16;
1467        const int h = drm_rect_height(&plane_state->uapi.src) >> 16;
1468        const int min_width = intel_plane_min_width(plane, fb, 0, rotation);
1469        const int max_width = intel_plane_max_width(plane, fb, 0, rotation);
1470        const int max_height = intel_plane_max_height(plane, fb, 0, rotation);
1471        const int aux_plane = skl_main_to_aux_plane(fb, 0);
1472        const u32 alignment = intel_surf_alignment(fb, 0);
1473        u32 offset;
1474        int ret;
1475
1476        if (w > max_width || w < min_width || h > max_height) {
1477                drm_dbg_kms(&dev_priv->drm,
1478                            "requested Y/RGB source size %dx%d outside limits (min: %dx1 max: %dx%d)\n",
1479                            w, h, min_width, max_width, max_height);
1480                return -EINVAL;
1481        }
1482
1483        ret = skl_calc_main_surface_offset(plane_state, &x, &y, &offset);
1484        if (ret)
1485                return ret;
1486
1487        /*
1488         * CCS AUX surface doesn't have its own x/y offsets, we must make sure
1489         * they match with the main surface x/y offsets.
1490         */
1491        if (is_ccs_modifier(fb->modifier)) {
1492                while (!skl_check_main_ccs_coordinates(plane_state, x, y,
1493                                                       offset, aux_plane)) {
1494                        if (offset == 0)
1495                                break;
1496
1497                        offset = intel_plane_adjust_aligned_offset(&x, &y, plane_state, 0,
1498                                                                   offset, offset - alignment);
1499                }
1500
1501                if (x != plane_state->view.color_plane[aux_plane].x ||
1502                    y != plane_state->view.color_plane[aux_plane].y) {
1503                        drm_dbg_kms(&dev_priv->drm,
1504                                    "Unable to find suitable display surface offset due to CCS\n");
1505                        return -EINVAL;
1506                }
1507        }
1508
1509        if (DISPLAY_VER(dev_priv) >= 13)
1510                drm_WARN_ON(&dev_priv->drm, x > 65535 || y > 65535);
1511        else
1512                drm_WARN_ON(&dev_priv->drm, x > 8191 || y > 8191);
1513
1514        plane_state->view.color_plane[0].offset = offset;
1515        plane_state->view.color_plane[0].x = x;
1516        plane_state->view.color_plane[0].y = y;
1517
1518        /*
1519         * Put the final coordinates back so that the src
1520         * coordinate checks will see the right values.
1521         */
1522        drm_rect_translate_to(&plane_state->uapi.src,
1523                              x << 16, y << 16);
1524
1525        return 0;
1526}
1527
1528static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state)
1529{
1530        struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1531        struct drm_i915_private *i915 = to_i915(plane->base.dev);
1532        const struct drm_framebuffer *fb = plane_state->hw.fb;
1533        unsigned int rotation = plane_state->hw.rotation;
1534        int uv_plane = 1;
1535        int max_width = intel_plane_max_width(plane, fb, uv_plane, rotation);
1536        int max_height = intel_plane_max_height(plane, fb, uv_plane, rotation);
1537        int x = plane_state->uapi.src.x1 >> 17;
1538        int y = plane_state->uapi.src.y1 >> 17;
1539        int w = drm_rect_width(&plane_state->uapi.src) >> 17;
1540        int h = drm_rect_height(&plane_state->uapi.src) >> 17;
1541        u32 offset;
1542
1543        /* FIXME not quite sure how/if these apply to the chroma plane */
1544        if (w > max_width || h > max_height) {
1545                drm_dbg_kms(&i915->drm,
1546                            "CbCr source size %dx%d too big (limit %dx%d)\n",
1547                            w, h, max_width, max_height);
1548                return -EINVAL;
1549        }
1550
1551        intel_add_fb_offsets(&x, &y, plane_state, uv_plane);
1552        offset = intel_plane_compute_aligned_offset(&x, &y,
1553                                                    plane_state, uv_plane);
1554
1555        if (is_ccs_modifier(fb->modifier)) {
1556                int ccs_plane = main_to_ccs_plane(fb, uv_plane);
1557                u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset;
1558                u32 alignment = intel_surf_alignment(fb, uv_plane);
1559
1560                if (offset > aux_offset)
1561                        offset = intel_plane_adjust_aligned_offset(&x, &y,
1562                                                                   plane_state,
1563                                                                   uv_plane,
1564                                                                   offset,
1565                                                                   aux_offset & ~(alignment - 1));
1566
1567                while (!skl_check_main_ccs_coordinates(plane_state, x, y,
1568                                                       offset, ccs_plane)) {
1569                        if (offset == 0)
1570                                break;
1571
1572                        offset = intel_plane_adjust_aligned_offset(&x, &y,
1573                                                                   plane_state,
1574                                                                   uv_plane,
1575                                                                   offset, offset - alignment);
1576                }
1577
1578                if (x != plane_state->view.color_plane[ccs_plane].x ||
1579                    y != plane_state->view.color_plane[ccs_plane].y) {
1580                        drm_dbg_kms(&i915->drm,
1581                                    "Unable to find suitable display surface offset due to CCS\n");
1582                        return -EINVAL;
1583                }
1584        }
1585
1586        if (DISPLAY_VER(i915) >= 13)
1587                drm_WARN_ON(&i915->drm, x > 65535 || y > 65535);
1588        else
1589                drm_WARN_ON(&i915->drm, x > 8191 || y > 8191);
1590
1591        plane_state->view.color_plane[uv_plane].offset = offset;
1592        plane_state->view.color_plane[uv_plane].x = x;
1593        plane_state->view.color_plane[uv_plane].y = y;
1594
1595        return 0;
1596}
1597
1598static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state)
1599{
1600        const struct drm_framebuffer *fb = plane_state->hw.fb;
1601        int src_x = plane_state->uapi.src.x1 >> 16;
1602        int src_y = plane_state->uapi.src.y1 >> 16;
1603        u32 offset;
1604        int ccs_plane;
1605
1606        for (ccs_plane = 0; ccs_plane < fb->format->num_planes; ccs_plane++) {
1607                int main_hsub, main_vsub;
1608                int hsub, vsub;
1609                int x, y;
1610
1611                if (!is_ccs_plane(fb, ccs_plane) ||
1612                    is_gen12_ccs_cc_plane(fb, ccs_plane))
1613                        continue;
1614
1615                intel_fb_plane_get_subsampling(&main_hsub, &main_vsub, fb,
1616                                               skl_ccs_to_main_plane(fb, ccs_plane));
1617                intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane);
1618
1619                hsub *= main_hsub;
1620                vsub *= main_vsub;
1621                x = src_x / hsub;
1622                y = src_y / vsub;
1623
1624                intel_add_fb_offsets(&x, &y, plane_state, ccs_plane);
1625
1626                offset = intel_plane_compute_aligned_offset(&x, &y,
1627                                                            plane_state,
1628                                                            ccs_plane);
1629
1630                plane_state->view.color_plane[ccs_plane].offset = offset;
1631                plane_state->view.color_plane[ccs_plane].x = (x * hsub + src_x % hsub) / main_hsub;
1632                plane_state->view.color_plane[ccs_plane].y = (y * vsub + src_y % vsub) / main_vsub;
1633        }
1634
1635        return 0;
1636}
1637
1638static int skl_check_plane_surface(struct intel_plane_state *plane_state)
1639{
1640        const struct drm_framebuffer *fb = plane_state->hw.fb;
1641        int ret;
1642
1643        ret = intel_plane_compute_gtt(plane_state);
1644        if (ret)
1645                return ret;
1646
1647        if (!plane_state->uapi.visible)
1648                return 0;
1649
1650        /*
1651         * Handle the AUX surface first since the main surface setup depends on
1652         * it.
1653         */
1654        if (is_ccs_modifier(fb->modifier)) {
1655                ret = skl_check_ccs_aux_surface(plane_state);
1656                if (ret)
1657                        return ret;
1658        }
1659
1660        if (intel_format_info_is_yuv_semiplanar(fb->format,
1661                                                fb->modifier)) {
1662                ret = skl_check_nv12_aux_surface(plane_state);
1663                if (ret)
1664                        return ret;
1665        }
1666
1667        ret = skl_check_main_surface(plane_state);
1668        if (ret)
1669                return ret;
1670
1671        return 0;
1672}
1673
1674static bool skl_fb_scalable(const struct drm_framebuffer *fb)
1675{
1676        if (!fb)
1677                return false;
1678
1679        switch (fb->format->format) {
1680        case DRM_FORMAT_C8:
1681                return false;
1682        case DRM_FORMAT_XRGB16161616F:
1683        case DRM_FORMAT_ARGB16161616F:
1684        case DRM_FORMAT_XBGR16161616F:
1685        case DRM_FORMAT_ABGR16161616F:
1686                return DISPLAY_VER(to_i915(fb->dev)) >= 11;
1687        default:
1688                return true;
1689        }
1690}
1691
1692static int skl_plane_check(struct intel_crtc_state *crtc_state,
1693                           struct intel_plane_state *plane_state)
1694{
1695        struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1696        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1697        const struct drm_framebuffer *fb = plane_state->hw.fb;
1698        int min_scale = DRM_PLANE_HELPER_NO_SCALING;
1699        int max_scale = DRM_PLANE_HELPER_NO_SCALING;
1700        int ret;
1701
1702        ret = skl_plane_check_fb(crtc_state, plane_state);
1703        if (ret)
1704                return ret;
1705
1706        /* use scaler when colorkey is not required */
1707        if (!plane_state->ckey.flags && skl_fb_scalable(fb)) {
1708                min_scale = 1;
1709                max_scale = skl_plane_max_scale(dev_priv, fb);
1710        }
1711
1712        ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
1713                                                min_scale, max_scale, true);
1714        if (ret)
1715                return ret;
1716
1717        ret = skl_check_plane_surface(plane_state);
1718        if (ret)
1719                return ret;
1720
1721        if (!plane_state->uapi.visible)
1722                return 0;
1723
1724        ret = skl_plane_check_dst_coordinates(crtc_state, plane_state);
1725        if (ret)
1726                return ret;
1727
1728        ret = intel_plane_check_src_coordinates(plane_state);
1729        if (ret)
1730                return ret;
1731
1732        ret = skl_plane_check_nv12_rotation(plane_state);
1733        if (ret)
1734                return ret;
1735
1736        /* HW only has 8 bits pixel precision, disable plane if invisible */
1737        if (!(plane_state->hw.alpha >> 8))
1738                plane_state->uapi.visible = false;
1739
1740        plane_state->ctl = skl_plane_ctl(crtc_state, plane_state);
1741
1742        if (DISPLAY_VER(dev_priv) >= 10)
1743                plane_state->color_ctl = glk_plane_color_ctl(crtc_state,
1744                                                             plane_state);
1745
1746        if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
1747            icl_is_hdr_plane(dev_priv, plane->id))
1748                /* Enable and use MPEG-2 chroma siting */
1749                plane_state->cus_ctl = PLANE_CUS_ENABLE |
1750                        PLANE_CUS_HPHASE_0 |
1751                        PLANE_CUS_VPHASE_SIGN_NEGATIVE | PLANE_CUS_VPHASE_0_25;
1752        else
1753                plane_state->cus_ctl = 0;
1754
1755        return 0;
1756}
1757
1758static bool skl_plane_has_fbc(struct drm_i915_private *dev_priv,
1759                              enum pipe pipe, enum plane_id plane_id)
1760{
1761        if (!HAS_FBC(dev_priv))
1762                return false;
1763
1764        return pipe == PIPE_A && plane_id == PLANE_PRIMARY;
1765}
1766
1767static bool skl_plane_has_planar(struct drm_i915_private *dev_priv,
1768                                 enum pipe pipe, enum plane_id plane_id)
1769{
1770        /* Display WA #0870: skl, bxt */
1771        if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))
1772                return false;
1773
1774        if (DISPLAY_VER(dev_priv) == 9 && pipe == PIPE_C)
1775                return false;
1776
1777        if (plane_id != PLANE_PRIMARY && plane_id != PLANE_SPRITE0)
1778                return false;
1779
1780        return true;
1781}
1782
1783static const u32 *skl_get_plane_formats(struct drm_i915_private *dev_priv,
1784                                        enum pipe pipe, enum plane_id plane_id,
1785                                        int *num_formats)
1786{
1787        if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
1788                *num_formats = ARRAY_SIZE(skl_planar_formats);
1789                return skl_planar_formats;
1790        } else {
1791                *num_formats = ARRAY_SIZE(skl_plane_formats);
1792                return skl_plane_formats;
1793        }
1794}
1795
1796static const u32 *glk_get_plane_formats(struct drm_i915_private *dev_priv,
1797                                        enum pipe pipe, enum plane_id plane_id,
1798                                        int *num_formats)
1799{
1800        if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
1801                *num_formats = ARRAY_SIZE(glk_planar_formats);
1802                return glk_planar_formats;
1803        } else {
1804                *num_formats = ARRAY_SIZE(skl_plane_formats);
1805                return skl_plane_formats;
1806        }
1807}
1808
1809static const u32 *icl_get_plane_formats(struct drm_i915_private *dev_priv,
1810                                        enum pipe pipe, enum plane_id plane_id,
1811                                        int *num_formats)
1812{
1813        if (icl_is_hdr_plane(dev_priv, plane_id)) {
1814                *num_formats = ARRAY_SIZE(icl_hdr_plane_formats);
1815                return icl_hdr_plane_formats;
1816        } else if (icl_is_nv12_y_plane(dev_priv, plane_id)) {
1817                *num_formats = ARRAY_SIZE(icl_sdr_y_plane_formats);
1818                return icl_sdr_y_plane_formats;
1819        } else {
1820                *num_formats = ARRAY_SIZE(icl_sdr_uv_plane_formats);
1821                return icl_sdr_uv_plane_formats;
1822        }
1823}
1824
1825static bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
1826                              enum pipe pipe, enum plane_id plane_id)
1827{
1828        if (plane_id == PLANE_CURSOR)
1829                return false;
1830
1831        if (DISPLAY_VER(dev_priv) >= 11)
1832                return true;
1833
1834        if (IS_GEMINILAKE(dev_priv))
1835                return pipe != PIPE_C;
1836
1837        return pipe != PIPE_C &&
1838                (plane_id == PLANE_PRIMARY ||
1839                 plane_id == PLANE_SPRITE0);
1840}
1841
1842static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
1843                                           u32 format, u64 modifier)
1844{
1845        struct intel_plane *plane = to_intel_plane(_plane);
1846
1847        switch (modifier) {
1848        case DRM_FORMAT_MOD_LINEAR:
1849        case I915_FORMAT_MOD_X_TILED:
1850        case I915_FORMAT_MOD_Y_TILED:
1851        case I915_FORMAT_MOD_Yf_TILED:
1852                break;
1853        case I915_FORMAT_MOD_Y_TILED_CCS:
1854        case I915_FORMAT_MOD_Yf_TILED_CCS:
1855                if (!plane->has_ccs)
1856                        return false;
1857                break;
1858        default:
1859                return false;
1860        }
1861
1862        switch (format) {
1863        case DRM_FORMAT_XRGB8888:
1864        case DRM_FORMAT_XBGR8888:
1865        case DRM_FORMAT_ARGB8888:
1866        case DRM_FORMAT_ABGR8888:
1867                if (is_ccs_modifier(modifier))
1868                        return true;
1869                fallthrough;
1870        case DRM_FORMAT_RGB565:
1871        case DRM_FORMAT_XRGB2101010:
1872        case DRM_FORMAT_XBGR2101010:
1873        case DRM_FORMAT_ARGB2101010:
1874        case DRM_FORMAT_ABGR2101010:
1875        case DRM_FORMAT_YUYV:
1876        case DRM_FORMAT_YVYU:
1877        case DRM_FORMAT_UYVY:
1878        case DRM_FORMAT_VYUY:
1879        case DRM_FORMAT_NV12:
1880        case DRM_FORMAT_XYUV8888:
1881        case DRM_FORMAT_P010:
1882        case DRM_FORMAT_P012:
1883        case DRM_FORMAT_P016:
1884        case DRM_FORMAT_XVYU2101010:
1885                if (modifier == I915_FORMAT_MOD_Yf_TILED)
1886                        return true;
1887                fallthrough;
1888        case DRM_FORMAT_C8:
1889        case DRM_FORMAT_XBGR16161616F:
1890        case DRM_FORMAT_ABGR16161616F:
1891        case DRM_FORMAT_XRGB16161616F:
1892        case DRM_FORMAT_ARGB16161616F:
1893        case DRM_FORMAT_Y210:
1894        case DRM_FORMAT_Y212:
1895        case DRM_FORMAT_Y216:
1896        case DRM_FORMAT_XVYU12_16161616:
1897        case DRM_FORMAT_XVYU16161616:
1898                if (modifier == DRM_FORMAT_MOD_LINEAR ||
1899                    modifier == I915_FORMAT_MOD_X_TILED ||
1900                    modifier == I915_FORMAT_MOD_Y_TILED)
1901                        return true;
1902                fallthrough;
1903        default:
1904                return false;
1905        }
1906}
1907
1908static bool gen12_plane_supports_mc_ccs(struct drm_i915_private *dev_priv,
1909                                        enum plane_id plane_id)
1910{
1911        /* Wa_14010477008:tgl[a0..c0],rkl[all],dg1[all] */
1912        if (IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv) ||
1913            IS_TGL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_D0))
1914                return false;
1915
1916        /* Wa_22011186057 */
1917        if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0))
1918                return false;
1919
1920        return plane_id < PLANE_SPRITE4;
1921}
1922
1923static bool gen12_plane_format_mod_supported(struct drm_plane *_plane,
1924                                             u32 format, u64 modifier)
1925{
1926        struct drm_i915_private *dev_priv = to_i915(_plane->dev);
1927        struct intel_plane *plane = to_intel_plane(_plane);
1928
1929        switch (modifier) {
1930        case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
1931                if (!gen12_plane_supports_mc_ccs(dev_priv, plane->id))
1932                        return false;
1933                fallthrough;
1934        case DRM_FORMAT_MOD_LINEAR:
1935        case I915_FORMAT_MOD_X_TILED:
1936        case I915_FORMAT_MOD_Y_TILED:
1937                break;
1938        case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
1939        case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
1940                /* Wa_22011186057 */
1941                if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0))
1942                        return false;
1943                break;
1944        default:
1945                return false;
1946        }
1947
1948        switch (format) {
1949        case DRM_FORMAT_XRGB8888:
1950        case DRM_FORMAT_XBGR8888:
1951        case DRM_FORMAT_ARGB8888:
1952        case DRM_FORMAT_ABGR8888:
1953                if (is_ccs_modifier(modifier))
1954                        return true;
1955                fallthrough;
1956        case DRM_FORMAT_YUYV:
1957        case DRM_FORMAT_YVYU:
1958        case DRM_FORMAT_UYVY:
1959        case DRM_FORMAT_VYUY:
1960        case DRM_FORMAT_NV12:
1961        case DRM_FORMAT_XYUV8888:
1962        case DRM_FORMAT_P010:
1963        case DRM_FORMAT_P012:
1964        case DRM_FORMAT_P016:
1965                if (modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS)
1966                        return true;
1967                fallthrough;
1968        case DRM_FORMAT_RGB565:
1969        case DRM_FORMAT_XRGB2101010:
1970        case DRM_FORMAT_XBGR2101010:
1971        case DRM_FORMAT_ARGB2101010:
1972        case DRM_FORMAT_ABGR2101010:
1973        case DRM_FORMAT_XVYU2101010:
1974        case DRM_FORMAT_C8:
1975        case DRM_FORMAT_XBGR16161616F:
1976        case DRM_FORMAT_ABGR16161616F:
1977        case DRM_FORMAT_XRGB16161616F:
1978        case DRM_FORMAT_ARGB16161616F:
1979        case DRM_FORMAT_Y210:
1980        case DRM_FORMAT_Y212:
1981        case DRM_FORMAT_Y216:
1982        case DRM_FORMAT_XVYU12_16161616:
1983        case DRM_FORMAT_XVYU16161616:
1984                if (modifier == DRM_FORMAT_MOD_LINEAR ||
1985                    modifier == I915_FORMAT_MOD_X_TILED ||
1986                    modifier == I915_FORMAT_MOD_Y_TILED)
1987                        return true;
1988                fallthrough;
1989        default:
1990                return false;
1991        }
1992}
1993
1994static const u64 *gen12_get_plane_modifiers(struct drm_i915_private *dev_priv,
1995                                            enum plane_id plane_id)
1996{
1997        /* Wa_22011186057 */
1998        if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0))
1999                return adlp_step_a_plane_format_modifiers;
2000        else if (gen12_plane_supports_mc_ccs(dev_priv, plane_id))
2001                return gen12_plane_format_modifiers_mc_ccs;
2002        else
2003                return gen12_plane_format_modifiers_rc_ccs;
2004}
2005
2006static const struct drm_plane_funcs skl_plane_funcs = {
2007        .update_plane = drm_atomic_helper_update_plane,
2008        .disable_plane = drm_atomic_helper_disable_plane,
2009        .destroy = intel_plane_destroy,
2010        .atomic_duplicate_state = intel_plane_duplicate_state,
2011        .atomic_destroy_state = intel_plane_destroy_state,
2012        .format_mod_supported = skl_plane_format_mod_supported,
2013};
2014
2015static const struct drm_plane_funcs gen12_plane_funcs = {
2016        .update_plane = drm_atomic_helper_update_plane,
2017        .disable_plane = drm_atomic_helper_disable_plane,
2018        .destroy = intel_plane_destroy,
2019        .atomic_duplicate_state = intel_plane_duplicate_state,
2020        .atomic_destroy_state = intel_plane_destroy_state,
2021        .format_mod_supported = gen12_plane_format_mod_supported,
2022};
2023
2024static void
2025skl_plane_enable_flip_done(struct intel_plane *plane)
2026{
2027        struct drm_i915_private *i915 = to_i915(plane->base.dev);
2028        enum pipe pipe = plane->pipe;
2029
2030        spin_lock_irq(&i915->irq_lock);
2031        bdw_enable_pipe_irq(i915, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id));
2032        spin_unlock_irq(&i915->irq_lock);
2033}
2034
2035static void
2036skl_plane_disable_flip_done(struct intel_plane *plane)
2037{
2038        struct drm_i915_private *i915 = to_i915(plane->base.dev);
2039        enum pipe pipe = plane->pipe;
2040
2041        spin_lock_irq(&i915->irq_lock);
2042        bdw_disable_pipe_irq(i915, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id));
2043        spin_unlock_irq(&i915->irq_lock);
2044}
2045
2046struct intel_plane *
2047skl_universal_plane_create(struct drm_i915_private *dev_priv,
2048                           enum pipe pipe, enum plane_id plane_id)
2049{
2050        const struct drm_plane_funcs *plane_funcs;
2051        struct intel_plane *plane;
2052        enum drm_plane_type plane_type;
2053        unsigned int supported_rotations;
2054        unsigned int supported_csc;
2055        const u64 *modifiers;
2056        const u32 *formats;
2057        int num_formats;
2058        int ret;
2059
2060        plane = intel_plane_alloc();
2061        if (IS_ERR(plane))
2062                return plane;
2063
2064        plane->pipe = pipe;
2065        plane->id = plane_id;
2066        plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane_id);
2067
2068        plane->has_fbc = skl_plane_has_fbc(dev_priv, pipe, plane_id);
2069        if (plane->has_fbc) {
2070                struct intel_fbc *fbc = &dev_priv->fbc;
2071
2072                fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
2073        }
2074
2075        if (DISPLAY_VER(dev_priv) >= 11) {
2076                plane->min_width = icl_plane_min_width;
2077                plane->max_width = icl_plane_max_width;
2078                plane->max_height = icl_plane_max_height;
2079                plane->min_cdclk = icl_plane_min_cdclk;
2080        } else if (DISPLAY_VER(dev_priv) >= 10) {
2081                plane->max_width = glk_plane_max_width;
2082                plane->max_height = skl_plane_max_height;
2083                plane->min_cdclk = glk_plane_min_cdclk;
2084        } else {
2085                plane->max_width = skl_plane_max_width;
2086                plane->max_height = skl_plane_max_height;
2087                plane->min_cdclk = skl_plane_min_cdclk;
2088        }
2089
2090        plane->max_stride = skl_plane_max_stride;
2091        plane->update_plane = skl_update_plane;
2092        plane->disable_plane = skl_disable_plane;
2093        plane->get_hw_state = skl_plane_get_hw_state;
2094        plane->check_plane = skl_plane_check;
2095
2096        if (plane_id == PLANE_PRIMARY) {
2097                plane->need_async_flip_disable_wa = IS_DISPLAY_VER(dev_priv,
2098                                                                   9, 10);
2099                plane->async_flip = skl_plane_async_flip;
2100                plane->enable_flip_done = skl_plane_enable_flip_done;
2101                plane->disable_flip_done = skl_plane_disable_flip_done;
2102        }
2103
2104        if (DISPLAY_VER(dev_priv) >= 11)
2105                formats = icl_get_plane_formats(dev_priv, pipe,
2106                                                plane_id, &num_formats);
2107        else if (DISPLAY_VER(dev_priv) >= 10)
2108                formats = glk_get_plane_formats(dev_priv, pipe,
2109                                                plane_id, &num_formats);
2110        else
2111                formats = skl_get_plane_formats(dev_priv, pipe,
2112                                                plane_id, &num_formats);
2113
2114        plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, plane_id);
2115        if (DISPLAY_VER(dev_priv) >= 12) {
2116                modifiers = gen12_get_plane_modifiers(dev_priv, plane_id);
2117                plane_funcs = &gen12_plane_funcs;
2118        } else {
2119                if (plane->has_ccs)
2120                        modifiers = skl_plane_format_modifiers_ccs;
2121                else
2122                        modifiers = skl_plane_format_modifiers_noccs;
2123                plane_funcs = &skl_plane_funcs;
2124        }
2125
2126        if (plane_id == PLANE_PRIMARY)
2127                plane_type = DRM_PLANE_TYPE_PRIMARY;
2128        else
2129                plane_type = DRM_PLANE_TYPE_OVERLAY;
2130
2131        ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
2132                                       0, plane_funcs,
2133                                       formats, num_formats, modifiers,
2134                                       plane_type,
2135                                       "plane %d%c", plane_id + 1,
2136                                       pipe_name(pipe));
2137        if (ret)
2138                goto fail;
2139
2140        if (DISPLAY_VER(dev_priv) >= 13)
2141                supported_rotations = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
2142        else
2143                supported_rotations =
2144                        DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
2145                        DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
2146
2147        if (DISPLAY_VER(dev_priv) >= 11)
2148                supported_rotations |= DRM_MODE_REFLECT_X;
2149
2150        drm_plane_create_rotation_property(&plane->base,
2151                                           DRM_MODE_ROTATE_0,
2152                                           supported_rotations);
2153
2154        supported_csc = BIT(DRM_COLOR_YCBCR_BT601) | BIT(DRM_COLOR_YCBCR_BT709);
2155
2156        if (DISPLAY_VER(dev_priv) >= 10)
2157                supported_csc |= BIT(DRM_COLOR_YCBCR_BT2020);
2158
2159        drm_plane_create_color_properties(&plane->base,
2160                                          supported_csc,
2161                                          BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
2162                                          BIT(DRM_COLOR_YCBCR_FULL_RANGE),
2163                                          DRM_COLOR_YCBCR_BT709,
2164                                          DRM_COLOR_YCBCR_LIMITED_RANGE);
2165
2166        drm_plane_create_alpha_property(&plane->base);
2167        drm_plane_create_blend_mode_property(&plane->base,
2168                                             BIT(DRM_MODE_BLEND_PIXEL_NONE) |
2169                                             BIT(DRM_MODE_BLEND_PREMULTI) |
2170                                             BIT(DRM_MODE_BLEND_COVERAGE));
2171
2172        drm_plane_create_zpos_immutable_property(&plane->base, plane_id);
2173
2174        if (DISPLAY_VER(dev_priv) >= 12)
2175                drm_plane_enable_fb_damage_clips(&plane->base);
2176
2177        if (DISPLAY_VER(dev_priv) >= 11)
2178                drm_plane_create_scaling_filter_property(&plane->base,
2179                                                BIT(DRM_SCALING_FILTER_DEFAULT) |
2180                                                BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
2181
2182        intel_plane_helper_add(plane);
2183
2184        return plane;
2185
2186fail:
2187        intel_plane_free(plane);
2188
2189        return ERR_PTR(ret);
2190}
2191
2192void
2193skl_get_initial_plane_config(struct intel_crtc *crtc,
2194                             struct intel_initial_plane_config *plane_config)
2195{
2196        struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state);
2197        struct drm_device *dev = crtc->base.dev;
2198        struct drm_i915_private *dev_priv = to_i915(dev);
2199        struct intel_plane *plane = to_intel_plane(crtc->base.primary);
2200        enum plane_id plane_id = plane->id;
2201        enum pipe pipe;
2202        u32 val, base, offset, stride_mult, tiling, alpha;
2203        int fourcc, pixel_format;
2204        unsigned int aligned_height;
2205        struct drm_framebuffer *fb;
2206        struct intel_framebuffer *intel_fb;
2207
2208        if (!plane->get_hw_state(plane, &pipe))
2209                return;
2210
2211        drm_WARN_ON(dev, pipe != crtc->pipe);
2212
2213        if (crtc_state->bigjoiner) {
2214                drm_dbg_kms(&dev_priv->drm,
2215                            "Unsupported bigjoiner configuration for initial FB\n");
2216                return;
2217        }
2218
2219        intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
2220        if (!intel_fb) {
2221                drm_dbg_kms(&dev_priv->drm, "failed to alloc fb\n");
2222                return;
2223        }
2224
2225        fb = &intel_fb->base;
2226
2227        fb->dev = dev;
2228
2229        val = intel_de_read(dev_priv, PLANE_CTL(pipe, plane_id));
2230
2231        if (DISPLAY_VER(dev_priv) >= 11)
2232                pixel_format = val & ICL_PLANE_CTL_FORMAT_MASK;
2233        else
2234                pixel_format = val & PLANE_CTL_FORMAT_MASK;
2235
2236        if (DISPLAY_VER(dev_priv) >= 10) {
2237                alpha = intel_de_read(dev_priv,
2238                                      PLANE_COLOR_CTL(pipe, plane_id));
2239                alpha &= PLANE_COLOR_ALPHA_MASK;
2240        } else {
2241                alpha = val & PLANE_CTL_ALPHA_MASK;
2242        }
2243
2244        fourcc = skl_format_to_fourcc(pixel_format,
2245                                      val & PLANE_CTL_ORDER_RGBX, alpha);
2246        fb->format = drm_format_info(fourcc);
2247
2248        tiling = val & PLANE_CTL_TILED_MASK;
2249        switch (tiling) {
2250        case PLANE_CTL_TILED_LINEAR:
2251                fb->modifier = DRM_FORMAT_MOD_LINEAR;
2252                break;
2253        case PLANE_CTL_TILED_X:
2254                plane_config->tiling = I915_TILING_X;
2255                fb->modifier = I915_FORMAT_MOD_X_TILED;
2256                break;
2257        case PLANE_CTL_TILED_Y:
2258                plane_config->tiling = I915_TILING_Y;
2259                if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
2260                        fb->modifier = DISPLAY_VER(dev_priv) >= 12 ?
2261                                I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS :
2262                                I915_FORMAT_MOD_Y_TILED_CCS;
2263                else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE)
2264                        fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS;
2265                else
2266                        fb->modifier = I915_FORMAT_MOD_Y_TILED;
2267                break;
2268        case PLANE_CTL_TILED_YF:
2269                if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
2270                        fb->modifier = I915_FORMAT_MOD_Yf_TILED_CCS;
2271                else
2272                        fb->modifier = I915_FORMAT_MOD_Yf_TILED;
2273                break;
2274        default:
2275                MISSING_CASE(tiling);
2276                goto error;
2277        }
2278
2279        /*
2280         * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr
2281         * while i915 HW rotation is clockwise, thats why this swapping.
2282         */
2283        switch (val & PLANE_CTL_ROTATE_MASK) {
2284        case PLANE_CTL_ROTATE_0:
2285                plane_config->rotation = DRM_MODE_ROTATE_0;
2286                break;
2287        case PLANE_CTL_ROTATE_90:
2288                plane_config->rotation = DRM_MODE_ROTATE_270;
2289                break;
2290        case PLANE_CTL_ROTATE_180:
2291                plane_config->rotation = DRM_MODE_ROTATE_180;
2292                break;
2293        case PLANE_CTL_ROTATE_270:
2294                plane_config->rotation = DRM_MODE_ROTATE_90;
2295                break;
2296        }
2297
2298        if (DISPLAY_VER(dev_priv) >= 11 && val & PLANE_CTL_FLIP_HORIZONTAL)
2299                plane_config->rotation |= DRM_MODE_REFLECT_X;
2300
2301        /* 90/270 degree rotation would require extra work */
2302        if (drm_rotation_90_or_270(plane_config->rotation))
2303                goto error;
2304
2305        base = intel_de_read(dev_priv, PLANE_SURF(pipe, plane_id)) & 0xfffff000;
2306        plane_config->base = base;
2307
2308        offset = intel_de_read(dev_priv, PLANE_OFFSET(pipe, plane_id));
2309
2310        val = intel_de_read(dev_priv, PLANE_SIZE(pipe, plane_id));
2311        fb->height = ((val >> 16) & 0xffff) + 1;
2312        fb->width = ((val >> 0) & 0xffff) + 1;
2313
2314        val = intel_de_read(dev_priv, PLANE_STRIDE(pipe, plane_id));
2315        stride_mult = skl_plane_stride_mult(fb, 0, DRM_MODE_ROTATE_0);
2316
2317        if (DISPLAY_VER(dev_priv) >= 13)
2318                fb->pitches[0] = (val & PLANE_STRIDE_MASK_XELPD) * stride_mult;
2319        else
2320                fb->pitches[0] = (val & PLANE_STRIDE_MASK) * stride_mult;
2321
2322        aligned_height = intel_fb_align_height(fb, 0, fb->height);
2323
2324        plane_config->size = fb->pitches[0] * aligned_height;
2325
2326        drm_dbg_kms(&dev_priv->drm,
2327                    "%s/%s with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
2328                    crtc->base.name, plane->base.name, fb->width, fb->height,
2329                    fb->format->cpp[0] * 8, base, fb->pitches[0],
2330                    plane_config->size);
2331
2332        plane_config->fb = intel_fb;
2333        return;
2334
2335error:
2336        kfree(intel_fb);
2337}
2338