root/drivers/gpu/drm/i915/display/intel_sprite.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. is_planar_yuv_format
  2. intel_usecs_to_scanlines
  3. intel_pipe_update_start
  4. intel_pipe_update_end
  5. intel_plane_check_stride
  6. intel_plane_check_src_coordinates
  7. icl_is_hdr_plane
  8. skl_plane_max_stride
  9. skl_program_scaler
  10. icl_program_input_csc
  11. skl_program_plane
  12. skl_update_plane
  13. icl_update_slave
  14. skl_disable_plane
  15. skl_plane_get_hw_state
  16. i9xx_plane_linear_gamma
  17. chv_update_csc
  18. vlv_update_clrc
  19. vlv_sprite_ctl_crtc
  20. vlv_sprite_ctl
  21. vlv_update_gamma
  22. vlv_update_plane
  23. vlv_disable_plane
  24. vlv_plane_get_hw_state
  25. ivb_sprite_ctl_crtc
  26. ivb_sprite_ctl
  27. ivb_sprite_linear_gamma
  28. ivb_update_gamma
  29. ivb_update_plane
  30. ivb_disable_plane
  31. ivb_plane_get_hw_state
  32. g4x_sprite_max_stride
  33. g4x_sprite_ctl_crtc
  34. g4x_sprite_ctl
  35. g4x_update_gamma
  36. ilk_sprite_linear_gamma
  37. ilk_update_gamma
  38. g4x_update_plane
  39. g4x_disable_plane
  40. g4x_plane_get_hw_state
  41. intel_fb_scalable
  42. g4x_sprite_check_scaling
  43. g4x_sprite_check
  44. chv_plane_check_rotation
  45. vlv_sprite_check
  46. skl_plane_check_fb
  47. skl_plane_check_dst_coordinates
  48. skl_plane_check_nv12_rotation
  49. skl_plane_check
  50. has_dst_key_in_primary_plane
  51. intel_plane_set_ckey
  52. intel_sprite_set_colorkey_ioctl
  53. g4x_sprite_format_mod_supported
  54. snb_sprite_format_mod_supported
  55. vlv_sprite_format_mod_supported
  56. skl_plane_format_mod_supported
  57. skl_plane_has_fbc
  58. skl_plane_has_planar
  59. skl_get_plane_formats
  60. glk_get_plane_formats
  61. icl_get_plane_formats
  62. skl_plane_has_ccs
  63. skl_universal_plane_create
  64. intel_sprite_plane_create

   1 /*
   2  * Copyright © 2011 Intel Corporation
   3  *
   4  * Permission is hereby granted, free of charge, to any person obtaining a
   5  * copy of this software and associated documentation files (the "Software"),
   6  * to deal in the Software without restriction, including without limitation
   7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8  * and/or sell copies of the Software, and to permit persons to whom the
   9  * Software is furnished to do so, subject to the following conditions:
  10  *
  11  * The above copyright notice and this permission notice (including the next
  12  * paragraph) shall be included in all copies or substantial portions of the
  13  * Software.
  14  *
  15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21  * SOFTWARE.
  22  *
  23  * Authors:
  24  *   Jesse Barnes <jbarnes@virtuousgeek.org>
  25  *
  26  * New plane/sprite handling.
  27  *
  28  * The older chips had a separate interface for programming plane related
  29  * registers; newer ones are much simpler and we can use the new DRM plane
  30  * support.
  31  */
  32 
  33 #include <drm/drm_atomic.h>
  34 #include <drm/drm_atomic_helper.h>
  35 #include <drm/drm_color_mgmt.h>
  36 #include <drm/drm_crtc.h>
  37 #include <drm/drm_fourcc.h>
  38 #include <drm/drm_plane_helper.h>
  39 #include <drm/drm_rect.h>
  40 #include <drm/i915_drm.h>
  41 
  42 #include "i915_drv.h"
  43 #include "i915_trace.h"
  44 #include "intel_atomic_plane.h"
  45 #include "intel_display_types.h"
  46 #include "intel_frontbuffer.h"
  47 #include "intel_pm.h"
  48 #include "intel_psr.h"
  49 #include "intel_sprite.h"
  50 
  51 bool is_planar_yuv_format(u32 pixelformat)
  52 {
  53         switch (pixelformat) {
  54         case DRM_FORMAT_NV12:
  55         case DRM_FORMAT_P010:
  56         case DRM_FORMAT_P012:
  57         case DRM_FORMAT_P016:
  58                 return true;
  59         default:
  60                 return false;
  61         }
  62 }
  63 
  64 int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
  65                              int usecs)
  66 {
  67         /* paranoia */
  68         if (!adjusted_mode->crtc_htotal)
  69                 return 1;
  70 
  71         return DIV_ROUND_UP(usecs * adjusted_mode->crtc_clock,
  72                             1000 * adjusted_mode->crtc_htotal);
  73 }
  74 
  75 /* FIXME: We should instead only take spinlocks once for the entire update
  76  * instead of once per mmio. */
  77 #if IS_ENABLED(CONFIG_PROVE_LOCKING)
  78 #define VBLANK_EVASION_TIME_US 250
  79 #else
  80 #define VBLANK_EVASION_TIME_US 100
  81 #endif
  82 
  83 /**
  84  * intel_pipe_update_start() - start update of a set of display registers
  85  * @new_crtc_state: the new crtc state
  86  *
  87  * Mark the start of an update to pipe registers that should be updated
  88  * atomically regarding vblank. If the next vblank will happens within
  89  * the next 100 us, this function waits until the vblank passes.
  90  *
  91  * After a successful call to this function, interrupts will be disabled
  92  * until a subsequent call to intel_pipe_update_end(). That is done to
  93  * avoid random delays.
  94  */
  95 void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state)
  96 {
  97         struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
  98         struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
  99         const struct drm_display_mode *adjusted_mode = &new_crtc_state->base.adjusted_mode;
 100         long timeout = msecs_to_jiffies_timeout(1);
 101         int scanline, min, max, vblank_start;
 102         wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
 103         bool need_vlv_dsi_wa = (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
 104                 intel_crtc_has_type(new_crtc_state, INTEL_OUTPUT_DSI);
 105         DEFINE_WAIT(wait);
 106         u32 psr_status;
 107 
 108         vblank_start = adjusted_mode->crtc_vblank_start;
 109         if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
 110                 vblank_start = DIV_ROUND_UP(vblank_start, 2);
 111 
 112         /* FIXME needs to be calibrated sensibly */
 113         min = vblank_start - intel_usecs_to_scanlines(adjusted_mode,
 114                                                       VBLANK_EVASION_TIME_US);
 115         max = vblank_start - 1;
 116 
 117         if (min <= 0 || max <= 0)
 118                 goto irq_disable;
 119 
 120         if (WARN_ON(drm_crtc_vblank_get(&crtc->base)))
 121                 goto irq_disable;
 122 
 123         /*
 124          * Wait for psr to idle out after enabling the VBL interrupts
 125          * VBL interrupts will start the PSR exit and prevent a PSR
 126          * re-entry as well.
 127          */
 128         if (intel_psr_wait_for_idle(new_crtc_state, &psr_status))
 129                 DRM_ERROR("PSR idle timed out 0x%x, atomic update may fail\n",
 130                           psr_status);
 131 
 132         local_irq_disable();
 133 
 134         crtc->debug.min_vbl = min;
 135         crtc->debug.max_vbl = max;
 136         trace_i915_pipe_update_start(crtc);
 137 
 138         for (;;) {
 139                 /*
 140                  * prepare_to_wait() has a memory barrier, which guarantees
 141                  * other CPUs can see the task state update by the time we
 142                  * read the scanline.
 143                  */
 144                 prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
 145 
 146                 scanline = intel_get_crtc_scanline(crtc);
 147                 if (scanline < min || scanline > max)
 148                         break;
 149 
 150                 if (!timeout) {
 151                         DRM_ERROR("Potential atomic update failure on pipe %c\n",
 152                                   pipe_name(crtc->pipe));
 153                         break;
 154                 }
 155 
 156                 local_irq_enable();
 157 
 158                 timeout = schedule_timeout(timeout);
 159 
 160                 local_irq_disable();
 161         }
 162 
 163         finish_wait(wq, &wait);
 164 
 165         drm_crtc_vblank_put(&crtc->base);
 166 
 167         /*
 168          * On VLV/CHV DSI the scanline counter would appear to
 169          * increment approx. 1/3 of a scanline before start of vblank.
 170          * The registers still get latched at start of vblank however.
 171          * This means we must not write any registers on the first
 172          * line of vblank (since not the whole line is actually in
 173          * vblank). And unfortunately we can't use the interrupt to
 174          * wait here since it will fire too soon. We could use the
 175          * frame start interrupt instead since it will fire after the
 176          * critical scanline, but that would require more changes
 177          * in the interrupt code. So for now we'll just do the nasty
 178          * thing and poll for the bad scanline to pass us by.
 179          *
 180          * FIXME figure out if BXT+ DSI suffers from this as well
 181          */
 182         while (need_vlv_dsi_wa && scanline == vblank_start)
 183                 scanline = intel_get_crtc_scanline(crtc);
 184 
 185         crtc->debug.scanline_start = scanline;
 186         crtc->debug.start_vbl_time = ktime_get();
 187         crtc->debug.start_vbl_count = intel_crtc_get_vblank_counter(crtc);
 188 
 189         trace_i915_pipe_update_vblank_evaded(crtc);
 190         return;
 191 
 192 irq_disable:
 193         local_irq_disable();
 194 }
 195 
 196 /**
 197  * intel_pipe_update_end() - end update of a set of display registers
 198  * @new_crtc_state: the new crtc state
 199  *
 200  * Mark the end of an update started with intel_pipe_update_start(). This
 201  * re-enables interrupts and verifies the update was actually completed
 202  * before a vblank.
 203  */
 204 void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
 205 {
 206         struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
 207         enum pipe pipe = crtc->pipe;
 208         int scanline_end = intel_get_crtc_scanline(crtc);
 209         u32 end_vbl_count = intel_crtc_get_vblank_counter(crtc);
 210         ktime_t end_vbl_time = ktime_get();
 211         struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 212 
 213         trace_i915_pipe_update_end(crtc, end_vbl_count, scanline_end);
 214 
 215         /* We're still in the vblank-evade critical section, this can't race.
 216          * Would be slightly nice to just grab the vblank count and arm the
 217          * event outside of the critical section - the spinlock might spin for a
 218          * while ... */
 219         if (new_crtc_state->base.event) {
 220                 WARN_ON(drm_crtc_vblank_get(&crtc->base) != 0);
 221 
 222                 spin_lock(&crtc->base.dev->event_lock);
 223                 drm_crtc_arm_vblank_event(&crtc->base, new_crtc_state->base.event);
 224                 spin_unlock(&crtc->base.dev->event_lock);
 225 
 226                 new_crtc_state->base.event = NULL;
 227         }
 228 
 229         local_irq_enable();
 230 
 231         if (intel_vgpu_active(dev_priv))
 232                 return;
 233 
 234         if (crtc->debug.start_vbl_count &&
 235             crtc->debug.start_vbl_count != end_vbl_count) {
 236                 DRM_ERROR("Atomic update failure on pipe %c (start=%u end=%u) time %lld us, min %d, max %d, scanline start %d, end %d\n",
 237                           pipe_name(pipe), crtc->debug.start_vbl_count,
 238                           end_vbl_count,
 239                           ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time),
 240                           crtc->debug.min_vbl, crtc->debug.max_vbl,
 241                           crtc->debug.scanline_start, scanline_end);
 242         }
 243 #ifdef CONFIG_DRM_I915_DEBUG_VBLANK_EVADE
 244         else if (ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time) >
 245                  VBLANK_EVASION_TIME_US)
 246                 DRM_WARN("Atomic update on pipe (%c) took %lld us, max time under evasion is %u us\n",
 247                          pipe_name(pipe),
 248                          ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time),
 249                          VBLANK_EVASION_TIME_US);
 250 #endif
 251 }
 252 
 253 int intel_plane_check_stride(const struct intel_plane_state *plane_state)
 254 {
 255         struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
 256         const struct drm_framebuffer *fb = plane_state->base.fb;
 257         unsigned int rotation = plane_state->base.rotation;
 258         u32 stride, max_stride;
 259 
 260         /*
 261          * We ignore stride for all invisible planes that
 262          * can be remapped. Otherwise we could end up
 263          * with a false positive when the remapping didn't
 264          * kick in due the plane being invisible.
 265          */
 266         if (intel_plane_can_remap(plane_state) &&
 267             !plane_state->base.visible)
 268                 return 0;
 269 
 270         /* FIXME other color planes? */
 271         stride = plane_state->color_plane[0].stride;
 272         max_stride = plane->max_stride(plane, fb->format->format,
 273                                        fb->modifier, rotation);
 274 
 275         if (stride > max_stride) {
 276                 DRM_DEBUG_KMS("[FB:%d] stride (%d) exceeds [PLANE:%d:%s] max stride (%d)\n",
 277                               fb->base.id, stride,
 278                               plane->base.base.id, plane->base.name, max_stride);
 279                 return -EINVAL;
 280         }
 281 
 282         return 0;
 283 }
 284 
 285 int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
 286 {
 287         const struct drm_framebuffer *fb = plane_state->base.fb;
 288         struct drm_rect *src = &plane_state->base.src;
 289         u32 src_x, src_y, src_w, src_h, hsub, vsub;
 290         bool rotated = drm_rotation_90_or_270(plane_state->base.rotation);
 291 
 292         /*
 293          * Hardware doesn't handle subpixel coordinates.
 294          * Adjust to (macro)pixel boundary, but be careful not to
 295          * increase the source viewport size, because that could
 296          * push the downscaling factor out of bounds.
 297          */
 298         src_x = src->x1 >> 16;
 299         src_w = drm_rect_width(src) >> 16;
 300         src_y = src->y1 >> 16;
 301         src_h = drm_rect_height(src) >> 16;
 302 
 303         src->x1 = src_x << 16;
 304         src->x2 = (src_x + src_w) << 16;
 305         src->y1 = src_y << 16;
 306         src->y2 = (src_y + src_h) << 16;
 307 
 308         if (!fb->format->is_yuv)
 309                 return 0;
 310 
 311         /* YUV specific checks */
 312         if (!rotated) {
 313                 hsub = fb->format->hsub;
 314                 vsub = fb->format->vsub;
 315         } else {
 316                 hsub = vsub = max(fb->format->hsub, fb->format->vsub);
 317         }
 318 
 319         if (src_x % hsub || src_w % hsub) {
 320                 DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of %u for %sYUV planes\n",
 321                               src_x, src_w, hsub, rotated ? "rotated " : "");
 322                 return -EINVAL;
 323         }
 324 
 325         if (src_y % vsub || src_h % vsub) {
 326                 DRM_DEBUG_KMS("src y/h (%u, %u) must be a multiple of %u for %sYUV planes\n",
 327                               src_y, src_h, vsub, rotated ? "rotated " : "");
 328                 return -EINVAL;
 329         }
 330 
 331         return 0;
 332 }
 333 
 334 bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id)
 335 {
 336         return INTEL_GEN(dev_priv) >= 11 &&
 337                 icl_hdr_plane_mask() & BIT(plane_id);
 338 }
 339 
 340 static unsigned int
 341 skl_plane_max_stride(struct intel_plane *plane,
 342                      u32 pixel_format, u64 modifier,
 343                      unsigned int rotation)
 344 {
 345         const struct drm_format_info *info = drm_format_info(pixel_format);
 346         int cpp = info->cpp[0];
 347 
 348         /*
 349          * "The stride in bytes must not exceed the
 350          * of the size of 8K pixels and 32K bytes."
 351          */
 352         if (drm_rotation_90_or_270(rotation))
 353                 return min(8192, 32768 / cpp);
 354         else
 355                 return min(8192 * cpp, 32768);
 356 }
 357 
 358 static void
 359 skl_program_scaler(struct intel_plane *plane,
 360                    const struct intel_crtc_state *crtc_state,
 361                    const struct intel_plane_state *plane_state)
 362 {
 363         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 364         enum pipe pipe = plane->pipe;
 365         int scaler_id = plane_state->scaler_id;
 366         const struct intel_scaler *scaler =
 367                 &crtc_state->scaler_state.scalers[scaler_id];
 368         int crtc_x = plane_state->base.dst.x1;
 369         int crtc_y = plane_state->base.dst.y1;
 370         u32 crtc_w = drm_rect_width(&plane_state->base.dst);
 371         u32 crtc_h = drm_rect_height(&plane_state->base.dst);
 372         u16 y_hphase, uv_rgb_hphase;
 373         u16 y_vphase, uv_rgb_vphase;
 374         int hscale, vscale;
 375 
 376         hscale = drm_rect_calc_hscale(&plane_state->base.src,
 377                                       &plane_state->base.dst,
 378                                       0, INT_MAX);
 379         vscale = drm_rect_calc_vscale(&plane_state->base.src,
 380                                       &plane_state->base.dst,
 381                                       0, INT_MAX);
 382 
 383         /* TODO: handle sub-pixel coordinates */
 384         if (is_planar_yuv_format(plane_state->base.fb->format->format) &&
 385             !icl_is_hdr_plane(dev_priv, plane->id)) {
 386                 y_hphase = skl_scaler_calc_phase(1, hscale, false);
 387                 y_vphase = skl_scaler_calc_phase(1, vscale, false);
 388 
 389                 /* MPEG2 chroma siting convention */
 390                 uv_rgb_hphase = skl_scaler_calc_phase(2, hscale, true);
 391                 uv_rgb_vphase = skl_scaler_calc_phase(2, vscale, false);
 392         } else {
 393                 /* not used */
 394                 y_hphase = 0;
 395                 y_vphase = 0;
 396 
 397                 uv_rgb_hphase = skl_scaler_calc_phase(1, hscale, false);
 398                 uv_rgb_vphase = skl_scaler_calc_phase(1, vscale, false);
 399         }
 400 
 401         I915_WRITE_FW(SKL_PS_CTRL(pipe, scaler_id),
 402                       PS_SCALER_EN | PS_PLANE_SEL(plane->id) | scaler->mode);
 403         I915_WRITE_FW(SKL_PS_VPHASE(pipe, scaler_id),
 404                       PS_Y_PHASE(y_vphase) | PS_UV_RGB_PHASE(uv_rgb_vphase));
 405         I915_WRITE_FW(SKL_PS_HPHASE(pipe, scaler_id),
 406                       PS_Y_PHASE(y_hphase) | PS_UV_RGB_PHASE(uv_rgb_hphase));
 407         I915_WRITE_FW(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y);
 408         I915_WRITE_FW(SKL_PS_WIN_SZ(pipe, scaler_id), (crtc_w << 16) | crtc_h);
 409 }
 410 
 411 /* Preoffset values for YUV to RGB Conversion */
 412 #define PREOFF_YUV_TO_RGB_HI            0x1800
 413 #define PREOFF_YUV_TO_RGB_ME            0x1F00
 414 #define PREOFF_YUV_TO_RGB_LO            0x1800
 415 
 416 #define  ROFF(x)          (((x) & 0xffff) << 16)
 417 #define  GOFF(x)          (((x) & 0xffff) << 0)
 418 #define  BOFF(x)          (((x) & 0xffff) << 16)
 419 
 420 static void
 421 icl_program_input_csc(struct intel_plane *plane,
 422                       const struct intel_crtc_state *crtc_state,
 423                       const struct intel_plane_state *plane_state)
 424 {
 425         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 426         enum pipe pipe = plane->pipe;
 427         enum plane_id plane_id = plane->id;
 428 
 429         static const u16 input_csc_matrix[][9] = {
 430                 /*
 431                  * BT.601 full range YCbCr -> full range RGB
 432                  * The matrix required is :
 433                  * [1.000, 0.000, 1.371,
 434                  *  1.000, -0.336, -0.698,
 435                  *  1.000, 1.732, 0.0000]
 436                  */
 437                 [DRM_COLOR_YCBCR_BT601] = {
 438                         0x7AF8, 0x7800, 0x0,
 439                         0x8B28, 0x7800, 0x9AC0,
 440                         0x0, 0x7800, 0x7DD8,
 441                 },
 442                 /*
 443                  * BT.709 full range YCbCr -> full range RGB
 444                  * The matrix required is :
 445                  * [1.000, 0.000, 1.574,
 446                  *  1.000, -0.187, -0.468,
 447                  *  1.000, 1.855, 0.0000]
 448                  */
 449                 [DRM_COLOR_YCBCR_BT709] = {
 450                         0x7C98, 0x7800, 0x0,
 451                         0x9EF8, 0x7800, 0xAC00,
 452                         0x0, 0x7800,  0x7ED8,
 453                 },
 454                 /*
 455                  * BT.2020 full range YCbCr -> full range RGB
 456                  * The matrix required is :
 457                  * [1.000, 0.000, 1.474,
 458                  *  1.000, -0.1645, -0.5713,
 459                  *  1.000, 1.8814, 0.0000]
 460                  */
 461                 [DRM_COLOR_YCBCR_BT2020] = {
 462                         0x7BC8, 0x7800, 0x0,
 463                         0x8928, 0x7800, 0xAA88,
 464                         0x0, 0x7800, 0x7F10,
 465                 },
 466         };
 467 
 468         /* Matrix for Limited Range to Full Range Conversion */
 469         static const u16 input_csc_matrix_lr[][9] = {
 470                 /*
 471                  * BT.601 Limted range YCbCr -> full range RGB
 472                  * The matrix required is :
 473                  * [1.164384, 0.000, 1.596027,
 474                  *  1.164384, -0.39175, -0.812813,
 475                  *  1.164384, 2.017232, 0.0000]
 476                  */
 477                 [DRM_COLOR_YCBCR_BT601] = {
 478                         0x7CC8, 0x7950, 0x0,
 479                         0x8D00, 0x7950, 0x9C88,
 480                         0x0, 0x7950, 0x6810,
 481                 },
 482                 /*
 483                  * BT.709 Limited range YCbCr -> full range RGB
 484                  * The matrix required is :
 485                  * [1.164384, 0.000, 1.792741,
 486                  *  1.164384, -0.213249, -0.532909,
 487                  *  1.164384, 2.112402, 0.0000]
 488                  */
 489                 [DRM_COLOR_YCBCR_BT709] = {
 490                         0x7E58, 0x7950, 0x0,
 491                         0x8888, 0x7950, 0xADA8,
 492                         0x0, 0x7950,  0x6870,
 493                 },
 494                 /*
 495                  * BT.2020 Limited range YCbCr -> full range RGB
 496                  * The matrix required is :
 497                  * [1.164, 0.000, 1.678,
 498                  *  1.164, -0.1873, -0.6504,
 499                  *  1.164, 2.1417, 0.0000]
 500                  */
 501                 [DRM_COLOR_YCBCR_BT2020] = {
 502                         0x7D70, 0x7950, 0x0,
 503                         0x8A68, 0x7950, 0xAC00,
 504                         0x0, 0x7950, 0x6890,
 505                 },
 506         };
 507         const u16 *csc;
 508 
 509         if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
 510                 csc = input_csc_matrix[plane_state->base.color_encoding];
 511         else
 512                 csc = input_csc_matrix_lr[plane_state->base.color_encoding];
 513 
 514         I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 0), ROFF(csc[0]) |
 515                       GOFF(csc[1]));
 516         I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 1), BOFF(csc[2]));
 517         I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 2), ROFF(csc[3]) |
 518                       GOFF(csc[4]));
 519         I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 3), BOFF(csc[5]));
 520         I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 4), ROFF(csc[6]) |
 521                       GOFF(csc[7]));
 522         I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 5), BOFF(csc[8]));
 523 
 524         I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 0),
 525                       PREOFF_YUV_TO_RGB_HI);
 526         if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
 527                 I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1), 0);
 528         else
 529                 I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1),
 530                               PREOFF_YUV_TO_RGB_ME);
 531         I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 2),
 532                       PREOFF_YUV_TO_RGB_LO);
 533         I915_WRITE_FW(PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 0), 0x0);
 534         I915_WRITE_FW(PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 1), 0x0);
 535         I915_WRITE_FW(PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 2), 0x0);
 536 }
 537 
 538 static void
 539 skl_program_plane(struct intel_plane *plane,
 540                   const struct intel_crtc_state *crtc_state,
 541                   const struct intel_plane_state *plane_state,
 542                   int color_plane, bool slave, u32 plane_ctl)
 543 {
 544         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 545         enum plane_id plane_id = plane->id;
 546         enum pipe pipe = plane->pipe;
 547         const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
 548         u32 surf_addr = plane_state->color_plane[color_plane].offset;
 549         u32 stride = skl_plane_stride(plane_state, color_plane);
 550         u32 aux_stride = skl_plane_stride(plane_state, 1);
 551         int crtc_x = plane_state->base.dst.x1;
 552         int crtc_y = plane_state->base.dst.y1;
 553         u32 x = plane_state->color_plane[color_plane].x;
 554         u32 y = plane_state->color_plane[color_plane].y;
 555         u32 src_w = drm_rect_width(&plane_state->base.src) >> 16;
 556         u32 src_h = drm_rect_height(&plane_state->base.src) >> 16;
 557         struct intel_plane *linked = plane_state->linked_plane;
 558         const struct drm_framebuffer *fb = plane_state->base.fb;
 559         u8 alpha = plane_state->base.alpha >> 8;
 560         u32 plane_color_ctl = 0;
 561         unsigned long irqflags;
 562         u32 keymsk, keymax;
 563 
 564         plane_ctl |= skl_plane_ctl_crtc(crtc_state);
 565 
 566         if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
 567                 plane_color_ctl = plane_state->color_ctl |
 568                         glk_plane_color_ctl_crtc(crtc_state);
 569 
 570         /* Sizes are 0 based */
 571         src_w--;
 572         src_h--;
 573 
 574         keymax = (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha);
 575 
 576         keymsk = key->channel_mask & 0x7ffffff;
 577         if (alpha < 0xff)
 578                 keymsk |= PLANE_KEYMSK_ALPHA_ENABLE;
 579 
 580         /* The scaler will handle the output position */
 581         if (plane_state->scaler_id >= 0) {
 582                 crtc_x = 0;
 583                 crtc_y = 0;
 584         }
 585 
 586         spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 587 
 588         I915_WRITE_FW(PLANE_STRIDE(pipe, plane_id), stride);
 589         I915_WRITE_FW(PLANE_POS(pipe, plane_id), (crtc_y << 16) | crtc_x);
 590         I915_WRITE_FW(PLANE_SIZE(pipe, plane_id), (src_h << 16) | src_w);
 591         I915_WRITE_FW(PLANE_AUX_DIST(pipe, plane_id),
 592                       (plane_state->color_plane[1].offset - surf_addr) | aux_stride);
 593 
 594         if (icl_is_hdr_plane(dev_priv, plane_id)) {
 595                 u32 cus_ctl = 0;
 596 
 597                 if (linked) {
 598                         /* Enable and use MPEG-2 chroma siting */
 599                         cus_ctl = PLANE_CUS_ENABLE |
 600                                 PLANE_CUS_HPHASE_0 |
 601                                 PLANE_CUS_VPHASE_SIGN_NEGATIVE |
 602                                 PLANE_CUS_VPHASE_0_25;
 603 
 604                         if (linked->id == PLANE_SPRITE5)
 605                                 cus_ctl |= PLANE_CUS_PLANE_7;
 606                         else if (linked->id == PLANE_SPRITE4)
 607                                 cus_ctl |= PLANE_CUS_PLANE_6;
 608                         else
 609                                 MISSING_CASE(linked->id);
 610                 }
 611 
 612                 I915_WRITE_FW(PLANE_CUS_CTL(pipe, plane_id), cus_ctl);
 613         }
 614 
 615         if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
 616                 I915_WRITE_FW(PLANE_COLOR_CTL(pipe, plane_id), plane_color_ctl);
 617 
 618         if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id))
 619                 icl_program_input_csc(plane, crtc_state, plane_state);
 620 
 621         skl_write_plane_wm(plane, crtc_state);
 622 
 623         I915_WRITE_FW(PLANE_KEYVAL(pipe, plane_id), key->min_value);
 624         I915_WRITE_FW(PLANE_KEYMSK(pipe, plane_id), keymsk);
 625         I915_WRITE_FW(PLANE_KEYMAX(pipe, plane_id), keymax);
 626 
 627         I915_WRITE_FW(PLANE_OFFSET(pipe, plane_id), (y << 16) | x);
 628 
 629         if (INTEL_GEN(dev_priv) < 11)
 630                 I915_WRITE_FW(PLANE_AUX_OFFSET(pipe, plane_id),
 631                               (plane_state->color_plane[1].y << 16) |
 632                               plane_state->color_plane[1].x);
 633 
 634         /*
 635          * The control register self-arms if the plane was previously
 636          * disabled. Try to make the plane enable atomic by writing
 637          * the control register just before the surface register.
 638          */
 639         I915_WRITE_FW(PLANE_CTL(pipe, plane_id), plane_ctl);
 640         I915_WRITE_FW(PLANE_SURF(pipe, plane_id),
 641                       intel_plane_ggtt_offset(plane_state) + surf_addr);
 642 
 643         if (!slave && plane_state->scaler_id >= 0)
 644                 skl_program_scaler(plane, crtc_state, plane_state);
 645 
 646         spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 647 }
 648 
 649 static void
 650 skl_update_plane(struct intel_plane *plane,
 651                  const struct intel_crtc_state *crtc_state,
 652                  const struct intel_plane_state *plane_state)
 653 {
 654         int color_plane = 0;
 655 
 656         if (plane_state->linked_plane) {
 657                 /* Program the UV plane */
 658                 color_plane = 1;
 659         }
 660 
 661         skl_program_plane(plane, crtc_state, plane_state,
 662                           color_plane, false, plane_state->ctl);
 663 }
 664 
 665 static void
 666 icl_update_slave(struct intel_plane *plane,
 667                  const struct intel_crtc_state *crtc_state,
 668                  const struct intel_plane_state *plane_state)
 669 {
 670         skl_program_plane(plane, crtc_state, plane_state, 0, true,
 671                           plane_state->ctl | PLANE_CTL_YUV420_Y_PLANE);
 672 }
 673 
 674 static void
 675 skl_disable_plane(struct intel_plane *plane,
 676                   const struct intel_crtc_state *crtc_state)
 677 {
 678         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 679         enum plane_id plane_id = plane->id;
 680         enum pipe pipe = plane->pipe;
 681         unsigned long irqflags;
 682 
 683         spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 684 
 685         if (icl_is_hdr_plane(dev_priv, plane_id))
 686                 I915_WRITE_FW(PLANE_CUS_CTL(pipe, plane_id), 0);
 687 
 688         skl_write_plane_wm(plane, crtc_state);
 689 
 690         I915_WRITE_FW(PLANE_CTL(pipe, plane_id), 0);
 691         I915_WRITE_FW(PLANE_SURF(pipe, plane_id), 0);
 692 
 693         spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 694 }
 695 
 696 static bool
 697 skl_plane_get_hw_state(struct intel_plane *plane,
 698                        enum pipe *pipe)
 699 {
 700         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 701         enum intel_display_power_domain power_domain;
 702         enum plane_id plane_id = plane->id;
 703         intel_wakeref_t wakeref;
 704         bool ret;
 705 
 706         power_domain = POWER_DOMAIN_PIPE(plane->pipe);
 707         wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
 708         if (!wakeref)
 709                 return false;
 710 
 711         ret = I915_READ(PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;
 712 
 713         *pipe = plane->pipe;
 714 
 715         intel_display_power_put(dev_priv, power_domain, wakeref);
 716 
 717         return ret;
 718 }
 719 
 720 static void i9xx_plane_linear_gamma(u16 gamma[8])
 721 {
 722         /* The points are not evenly spaced. */
 723         static const u8 in[8] = { 0, 1, 2, 4, 8, 16, 24, 32 };
 724         int i;
 725 
 726         for (i = 0; i < 8; i++)
 727                 gamma[i] = (in[i] << 8) / 32;
 728 }
 729 
 730 static void
 731 chv_update_csc(const struct intel_plane_state *plane_state)
 732 {
 733         struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
 734         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 735         const struct drm_framebuffer *fb = plane_state->base.fb;
 736         enum plane_id plane_id = plane->id;
 737         /*
 738          * |r|   | c0 c1 c2 |   |cr|
 739          * |g| = | c3 c4 c5 | x |y |
 740          * |b|   | c6 c7 c8 |   |cb|
 741          *
 742          * Coefficients are s3.12.
 743          *
 744          * Cb and Cr apparently come in as signed already, and
 745          * we always get full range data in on account of CLRC0/1.
 746          */
 747         static const s16 csc_matrix[][9] = {
 748                 /* BT.601 full range YCbCr -> full range RGB */
 749                 [DRM_COLOR_YCBCR_BT601] = {
 750                          5743, 4096,     0,
 751                         -2925, 4096, -1410,
 752                             0, 4096,  7258,
 753                 },
 754                 /* BT.709 full range YCbCr -> full range RGB */
 755                 [DRM_COLOR_YCBCR_BT709] = {
 756                          6450, 4096,     0,
 757                         -1917, 4096,  -767,
 758                             0, 4096,  7601,
 759                 },
 760         };
 761         const s16 *csc = csc_matrix[plane_state->base.color_encoding];
 762 
 763         /* Seems RGB data bypasses the CSC always */
 764         if (!fb->format->is_yuv)
 765                 return;
 766 
 767         I915_WRITE_FW(SPCSCYGOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
 768         I915_WRITE_FW(SPCSCCBOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
 769         I915_WRITE_FW(SPCSCCROFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
 770 
 771         I915_WRITE_FW(SPCSCC01(plane_id), SPCSC_C1(csc[1]) | SPCSC_C0(csc[0]));
 772         I915_WRITE_FW(SPCSCC23(plane_id), SPCSC_C1(csc[3]) | SPCSC_C0(csc[2]));
 773         I915_WRITE_FW(SPCSCC45(plane_id), SPCSC_C1(csc[5]) | SPCSC_C0(csc[4]));
 774         I915_WRITE_FW(SPCSCC67(plane_id), SPCSC_C1(csc[7]) | SPCSC_C0(csc[6]));
 775         I915_WRITE_FW(SPCSCC8(plane_id), SPCSC_C0(csc[8]));
 776 
 777         I915_WRITE_FW(SPCSCYGICLAMP(plane_id), SPCSC_IMAX(1023) | SPCSC_IMIN(0));
 778         I915_WRITE_FW(SPCSCCBICLAMP(plane_id), SPCSC_IMAX(512) | SPCSC_IMIN(-512));
 779         I915_WRITE_FW(SPCSCCRICLAMP(plane_id), SPCSC_IMAX(512) | SPCSC_IMIN(-512));
 780 
 781         I915_WRITE_FW(SPCSCYGOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
 782         I915_WRITE_FW(SPCSCCBOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
 783         I915_WRITE_FW(SPCSCCROCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
 784 }
 785 
 786 #define SIN_0 0
 787 #define COS_0 1
 788 
 789 static void
 790 vlv_update_clrc(const struct intel_plane_state *plane_state)
 791 {
 792         struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
 793         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 794         const struct drm_framebuffer *fb = plane_state->base.fb;
 795         enum pipe pipe = plane->pipe;
 796         enum plane_id plane_id = plane->id;
 797         int contrast, brightness, sh_scale, sh_sin, sh_cos;
 798 
 799         if (fb->format->is_yuv &&
 800             plane_state->base.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) {
 801                 /*
 802                  * Expand limited range to full range:
 803                  * Contrast is applied first and is used to expand Y range.
 804                  * Brightness is applied second and is used to remove the
 805                  * offset from Y. Saturation/hue is used to expand CbCr range.
 806                  */
 807                 contrast = DIV_ROUND_CLOSEST(255 << 6, 235 - 16);
 808                 brightness = -DIV_ROUND_CLOSEST(16 * 255, 235 - 16);
 809                 sh_scale = DIV_ROUND_CLOSEST(128 << 7, 240 - 128);
 810                 sh_sin = SIN_0 * sh_scale;
 811                 sh_cos = COS_0 * sh_scale;
 812         } else {
 813                 /* Pass-through everything. */
 814                 contrast = 1 << 6;
 815                 brightness = 0;
 816                 sh_scale = 1 << 7;
 817                 sh_sin = SIN_0 * sh_scale;
 818                 sh_cos = COS_0 * sh_scale;
 819         }
 820 
 821         /* FIXME these register are single buffered :( */
 822         I915_WRITE_FW(SPCLRC0(pipe, plane_id),
 823                       SP_CONTRAST(contrast) | SP_BRIGHTNESS(brightness));
 824         I915_WRITE_FW(SPCLRC1(pipe, plane_id),
 825                       SP_SH_SIN(sh_sin) | SP_SH_COS(sh_cos));
 826 }
 827 
 828 static u32 vlv_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
 829 {
 830         u32 sprctl = 0;
 831 
 832         if (crtc_state->gamma_enable)
 833                 sprctl |= SP_GAMMA_ENABLE;
 834 
 835         return sprctl;
 836 }
 837 
 838 static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
 839                           const struct intel_plane_state *plane_state)
 840 {
 841         const struct drm_framebuffer *fb = plane_state->base.fb;
 842         unsigned int rotation = plane_state->base.rotation;
 843         const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
 844         u32 sprctl;
 845 
 846         sprctl = SP_ENABLE;
 847 
 848         switch (fb->format->format) {
 849         case DRM_FORMAT_YUYV:
 850                 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
 851                 break;
 852         case DRM_FORMAT_YVYU:
 853                 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
 854                 break;
 855         case DRM_FORMAT_UYVY:
 856                 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
 857                 break;
 858         case DRM_FORMAT_VYUY:
 859                 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
 860                 break;
 861         case DRM_FORMAT_RGB565:
 862                 sprctl |= SP_FORMAT_BGR565;
 863                 break;
 864         case DRM_FORMAT_XRGB8888:
 865                 sprctl |= SP_FORMAT_BGRX8888;
 866                 break;
 867         case DRM_FORMAT_ARGB8888:
 868                 sprctl |= SP_FORMAT_BGRA8888;
 869                 break;
 870         case DRM_FORMAT_XBGR2101010:
 871                 sprctl |= SP_FORMAT_RGBX1010102;
 872                 break;
 873         case DRM_FORMAT_ABGR2101010:
 874                 sprctl |= SP_FORMAT_RGBA1010102;
 875                 break;
 876         case DRM_FORMAT_XBGR8888:
 877                 sprctl |= SP_FORMAT_RGBX8888;
 878                 break;
 879         case DRM_FORMAT_ABGR8888:
 880                 sprctl |= SP_FORMAT_RGBA8888;
 881                 break;
 882         default:
 883                 MISSING_CASE(fb->format->format);
 884                 return 0;
 885         }
 886 
 887         if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
 888                 sprctl |= SP_YUV_FORMAT_BT709;
 889 
 890         if (fb->modifier == I915_FORMAT_MOD_X_TILED)
 891                 sprctl |= SP_TILED;
 892 
 893         if (rotation & DRM_MODE_ROTATE_180)
 894                 sprctl |= SP_ROTATE_180;
 895 
 896         if (rotation & DRM_MODE_REFLECT_X)
 897                 sprctl |= SP_MIRROR;
 898 
 899         if (key->flags & I915_SET_COLORKEY_SOURCE)
 900                 sprctl |= SP_SOURCE_KEY;
 901 
 902         return sprctl;
 903 }
 904 
 905 static void vlv_update_gamma(const struct intel_plane_state *plane_state)
 906 {
 907         struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
 908         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 909         const struct drm_framebuffer *fb = plane_state->base.fb;
 910         enum pipe pipe = plane->pipe;
 911         enum plane_id plane_id = plane->id;
 912         u16 gamma[8];
 913         int i;
 914 
 915         /* Seems RGB data bypasses the gamma always */
 916         if (!fb->format->is_yuv)
 917                 return;
 918 
 919         i9xx_plane_linear_gamma(gamma);
 920 
 921         /* FIXME these register are single buffered :( */
 922         /* The two end points are implicit (0.0 and 1.0) */
 923         for (i = 1; i < 8 - 1; i++)
 924                 I915_WRITE_FW(SPGAMC(pipe, plane_id, i - 1),
 925                               gamma[i] << 16 |
 926                               gamma[i] << 8 |
 927                               gamma[i]);
 928 }
 929 
 930 static void
 931 vlv_update_plane(struct intel_plane *plane,
 932                  const struct intel_crtc_state *crtc_state,
 933                  const struct intel_plane_state *plane_state)
 934 {
 935         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 936         enum pipe pipe = plane->pipe;
 937         enum plane_id plane_id = plane->id;
 938         u32 sprsurf_offset = plane_state->color_plane[0].offset;
 939         u32 linear_offset;
 940         const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
 941         int crtc_x = plane_state->base.dst.x1;
 942         int crtc_y = plane_state->base.dst.y1;
 943         u32 crtc_w = drm_rect_width(&plane_state->base.dst);
 944         u32 crtc_h = drm_rect_height(&plane_state->base.dst);
 945         u32 x = plane_state->color_plane[0].x;
 946         u32 y = plane_state->color_plane[0].y;
 947         unsigned long irqflags;
 948         u32 sprctl;
 949 
 950         sprctl = plane_state->ctl | vlv_sprite_ctl_crtc(crtc_state);
 951 
 952         /* Sizes are 0 based */
 953         crtc_w--;
 954         crtc_h--;
 955 
 956         linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
 957 
 958         spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 959 
 960         I915_WRITE_FW(SPSTRIDE(pipe, plane_id),
 961                       plane_state->color_plane[0].stride);
 962         I915_WRITE_FW(SPPOS(pipe, plane_id), (crtc_y << 16) | crtc_x);
 963         I915_WRITE_FW(SPSIZE(pipe, plane_id), (crtc_h << 16) | crtc_w);
 964         I915_WRITE_FW(SPCONSTALPHA(pipe, plane_id), 0);
 965 
 966         if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
 967                 chv_update_csc(plane_state);
 968 
 969         if (key->flags) {
 970                 I915_WRITE_FW(SPKEYMINVAL(pipe, plane_id), key->min_value);
 971                 I915_WRITE_FW(SPKEYMSK(pipe, plane_id), key->channel_mask);
 972                 I915_WRITE_FW(SPKEYMAXVAL(pipe, plane_id), key->max_value);
 973         }
 974 
 975         I915_WRITE_FW(SPLINOFF(pipe, plane_id), linear_offset);
 976         I915_WRITE_FW(SPTILEOFF(pipe, plane_id), (y << 16) | x);
 977 
 978         /*
 979          * The control register self-arms if the plane was previously
 980          * disabled. Try to make the plane enable atomic by writing
 981          * the control register just before the surface register.
 982          */
 983         I915_WRITE_FW(SPCNTR(pipe, plane_id), sprctl);
 984         I915_WRITE_FW(SPSURF(pipe, plane_id),
 985                       intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
 986 
 987         vlv_update_clrc(plane_state);
 988         vlv_update_gamma(plane_state);
 989 
 990         spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 991 }
 992 
 993 static void
 994 vlv_disable_plane(struct intel_plane *plane,
 995                   const struct intel_crtc_state *crtc_state)
 996 {
 997         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 998         enum pipe pipe = plane->pipe;
 999         enum plane_id plane_id = plane->id;
1000         unsigned long irqflags;
1001 
1002         spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1003 
1004         I915_WRITE_FW(SPCNTR(pipe, plane_id), 0);
1005         I915_WRITE_FW(SPSURF(pipe, plane_id), 0);
1006 
1007         spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1008 }
1009 
1010 static bool
1011 vlv_plane_get_hw_state(struct intel_plane *plane,
1012                        enum pipe *pipe)
1013 {
1014         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1015         enum intel_display_power_domain power_domain;
1016         enum plane_id plane_id = plane->id;
1017         intel_wakeref_t wakeref;
1018         bool ret;
1019 
1020         power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1021         wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1022         if (!wakeref)
1023                 return false;
1024 
1025         ret = I915_READ(SPCNTR(plane->pipe, plane_id)) & SP_ENABLE;
1026 
1027         *pipe = plane->pipe;
1028 
1029         intel_display_power_put(dev_priv, power_domain, wakeref);
1030 
1031         return ret;
1032 }
1033 
1034 static u32 ivb_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
1035 {
1036         u32 sprctl = 0;
1037 
1038         if (crtc_state->gamma_enable)
1039                 sprctl |= SPRITE_GAMMA_ENABLE;
1040 
1041         if (crtc_state->csc_enable)
1042                 sprctl |= SPRITE_PIPE_CSC_ENABLE;
1043 
1044         return sprctl;
1045 }
1046 
1047 static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
1048                           const struct intel_plane_state *plane_state)
1049 {
1050         struct drm_i915_private *dev_priv =
1051                 to_i915(plane_state->base.plane->dev);
1052         const struct drm_framebuffer *fb = plane_state->base.fb;
1053         unsigned int rotation = plane_state->base.rotation;
1054         const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1055         u32 sprctl;
1056 
1057         sprctl = SPRITE_ENABLE;
1058 
1059         if (IS_IVYBRIDGE(dev_priv))
1060                 sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
1061 
1062         switch (fb->format->format) {
1063         case DRM_FORMAT_XBGR8888:
1064                 sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
1065                 break;
1066         case DRM_FORMAT_XRGB8888:
1067                 sprctl |= SPRITE_FORMAT_RGBX888;
1068                 break;
1069         case DRM_FORMAT_YUYV:
1070                 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
1071                 break;
1072         case DRM_FORMAT_YVYU:
1073                 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
1074                 break;
1075         case DRM_FORMAT_UYVY:
1076                 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
1077                 break;
1078         case DRM_FORMAT_VYUY:
1079                 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
1080                 break;
1081         default:
1082                 MISSING_CASE(fb->format->format);
1083                 return 0;
1084         }
1085 
1086         sprctl |= SPRITE_INT_GAMMA_DISABLE;
1087 
1088         if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
1089                 sprctl |= SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709;
1090 
1091         if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1092                 sprctl |= SPRITE_YUV_RANGE_CORRECTION_DISABLE;
1093 
1094         if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1095                 sprctl |= SPRITE_TILED;
1096 
1097         if (rotation & DRM_MODE_ROTATE_180)
1098                 sprctl |= SPRITE_ROTATE_180;
1099 
1100         if (key->flags & I915_SET_COLORKEY_DESTINATION)
1101                 sprctl |= SPRITE_DEST_KEY;
1102         else if (key->flags & I915_SET_COLORKEY_SOURCE)
1103                 sprctl |= SPRITE_SOURCE_KEY;
1104 
1105         return sprctl;
1106 }
1107 
1108 static void ivb_sprite_linear_gamma(u16 gamma[18])
1109 {
1110         int i;
1111 
1112         for (i = 0; i < 17; i++)
1113                 gamma[i] = (i << 10) / 16;
1114 
1115         gamma[i] = 3 << 10;
1116         i++;
1117 }
1118 
1119 static void ivb_update_gamma(const struct intel_plane_state *plane_state)
1120 {
1121         struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1122         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1123         enum pipe pipe = plane->pipe;
1124         u16 gamma[18];
1125         int i;
1126 
1127         ivb_sprite_linear_gamma(gamma);
1128 
1129         /* FIXME these register are single buffered :( */
1130         for (i = 0; i < 16; i++)
1131                 I915_WRITE_FW(SPRGAMC(pipe, i),
1132                               gamma[i] << 20 |
1133                               gamma[i] << 10 |
1134                               gamma[i]);
1135 
1136         I915_WRITE_FW(SPRGAMC16(pipe, 0), gamma[i]);
1137         I915_WRITE_FW(SPRGAMC16(pipe, 1), gamma[i]);
1138         I915_WRITE_FW(SPRGAMC16(pipe, 2), gamma[i]);
1139         i++;
1140 
1141         I915_WRITE_FW(SPRGAMC17(pipe, 0), gamma[i]);
1142         I915_WRITE_FW(SPRGAMC17(pipe, 1), gamma[i]);
1143         I915_WRITE_FW(SPRGAMC17(pipe, 2), gamma[i]);
1144         i++;
1145 }
1146 
1147 static void
1148 ivb_update_plane(struct intel_plane *plane,
1149                  const struct intel_crtc_state *crtc_state,
1150                  const struct intel_plane_state *plane_state)
1151 {
1152         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1153         enum pipe pipe = plane->pipe;
1154         u32 sprsurf_offset = plane_state->color_plane[0].offset;
1155         u32 linear_offset;
1156         const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1157         int crtc_x = plane_state->base.dst.x1;
1158         int crtc_y = plane_state->base.dst.y1;
1159         u32 crtc_w = drm_rect_width(&plane_state->base.dst);
1160         u32 crtc_h = drm_rect_height(&plane_state->base.dst);
1161         u32 x = plane_state->color_plane[0].x;
1162         u32 y = plane_state->color_plane[0].y;
1163         u32 src_w = drm_rect_width(&plane_state->base.src) >> 16;
1164         u32 src_h = drm_rect_height(&plane_state->base.src) >> 16;
1165         u32 sprctl, sprscale = 0;
1166         unsigned long irqflags;
1167 
1168         sprctl = plane_state->ctl | ivb_sprite_ctl_crtc(crtc_state);
1169 
1170         /* Sizes are 0 based */
1171         src_w--;
1172         src_h--;
1173         crtc_w--;
1174         crtc_h--;
1175 
1176         if (crtc_w != src_w || crtc_h != src_h)
1177                 sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
1178 
1179         linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1180 
1181         spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1182 
1183         I915_WRITE_FW(SPRSTRIDE(pipe), plane_state->color_plane[0].stride);
1184         I915_WRITE_FW(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
1185         I915_WRITE_FW(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
1186         if (IS_IVYBRIDGE(dev_priv))
1187                 I915_WRITE_FW(SPRSCALE(pipe), sprscale);
1188 
1189         if (key->flags) {
1190                 I915_WRITE_FW(SPRKEYVAL(pipe), key->min_value);
1191                 I915_WRITE_FW(SPRKEYMSK(pipe), key->channel_mask);
1192                 I915_WRITE_FW(SPRKEYMAX(pipe), key->max_value);
1193         }
1194 
1195         /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
1196          * register */
1197         if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
1198                 I915_WRITE_FW(SPROFFSET(pipe), (y << 16) | x);
1199         } else {
1200                 I915_WRITE_FW(SPRLINOFF(pipe), linear_offset);
1201                 I915_WRITE_FW(SPRTILEOFF(pipe), (y << 16) | x);
1202         }
1203 
1204         /*
1205          * The control register self-arms if the plane was previously
1206          * disabled. Try to make the plane enable atomic by writing
1207          * the control register just before the surface register.
1208          */
1209         I915_WRITE_FW(SPRCTL(pipe), sprctl);
1210         I915_WRITE_FW(SPRSURF(pipe),
1211                       intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
1212 
1213         ivb_update_gamma(plane_state);
1214 
1215         spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1216 }
1217 
1218 static void
1219 ivb_disable_plane(struct intel_plane *plane,
1220                   const struct intel_crtc_state *crtc_state)
1221 {
1222         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1223         enum pipe pipe = plane->pipe;
1224         unsigned long irqflags;
1225 
1226         spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1227 
1228         I915_WRITE_FW(SPRCTL(pipe), 0);
1229         /* Disable the scaler */
1230         if (IS_IVYBRIDGE(dev_priv))
1231                 I915_WRITE_FW(SPRSCALE(pipe), 0);
1232         I915_WRITE_FW(SPRSURF(pipe), 0);
1233 
1234         spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1235 }
1236 
1237 static bool
1238 ivb_plane_get_hw_state(struct intel_plane *plane,
1239                        enum pipe *pipe)
1240 {
1241         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1242         enum intel_display_power_domain power_domain;
1243         intel_wakeref_t wakeref;
1244         bool ret;
1245 
1246         power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1247         wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1248         if (!wakeref)
1249                 return false;
1250 
1251         ret =  I915_READ(SPRCTL(plane->pipe)) & SPRITE_ENABLE;
1252 
1253         *pipe = plane->pipe;
1254 
1255         intel_display_power_put(dev_priv, power_domain, wakeref);
1256 
1257         return ret;
1258 }
1259 
1260 static unsigned int
1261 g4x_sprite_max_stride(struct intel_plane *plane,
1262                       u32 pixel_format, u64 modifier,
1263                       unsigned int rotation)
1264 {
1265         return 16384;
1266 }
1267 
1268 static u32 g4x_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
1269 {
1270         u32 dvscntr = 0;
1271 
1272         if (crtc_state->gamma_enable)
1273                 dvscntr |= DVS_GAMMA_ENABLE;
1274 
1275         if (crtc_state->csc_enable)
1276                 dvscntr |= DVS_PIPE_CSC_ENABLE;
1277 
1278         return dvscntr;
1279 }
1280 
1281 static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
1282                           const struct intel_plane_state *plane_state)
1283 {
1284         struct drm_i915_private *dev_priv =
1285                 to_i915(plane_state->base.plane->dev);
1286         const struct drm_framebuffer *fb = plane_state->base.fb;
1287         unsigned int rotation = plane_state->base.rotation;
1288         const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1289         u32 dvscntr;
1290 
1291         dvscntr = DVS_ENABLE;
1292 
1293         if (IS_GEN(dev_priv, 6))
1294                 dvscntr |= DVS_TRICKLE_FEED_DISABLE;
1295 
1296         switch (fb->format->format) {
1297         case DRM_FORMAT_XBGR8888:
1298                 dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
1299                 break;
1300         case DRM_FORMAT_XRGB8888:
1301                 dvscntr |= DVS_FORMAT_RGBX888;
1302                 break;
1303         case DRM_FORMAT_YUYV:
1304                 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
1305                 break;
1306         case DRM_FORMAT_YVYU:
1307                 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
1308                 break;
1309         case DRM_FORMAT_UYVY:
1310                 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
1311                 break;
1312         case DRM_FORMAT_VYUY:
1313                 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
1314                 break;
1315         default:
1316                 MISSING_CASE(fb->format->format);
1317                 return 0;
1318         }
1319 
1320         if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
1321                 dvscntr |= DVS_YUV_FORMAT_BT709;
1322 
1323         if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1324                 dvscntr |= DVS_YUV_RANGE_CORRECTION_DISABLE;
1325 
1326         if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1327                 dvscntr |= DVS_TILED;
1328 
1329         if (rotation & DRM_MODE_ROTATE_180)
1330                 dvscntr |= DVS_ROTATE_180;
1331 
1332         if (key->flags & I915_SET_COLORKEY_DESTINATION)
1333                 dvscntr |= DVS_DEST_KEY;
1334         else if (key->flags & I915_SET_COLORKEY_SOURCE)
1335                 dvscntr |= DVS_SOURCE_KEY;
1336 
1337         return dvscntr;
1338 }
1339 
1340 static void g4x_update_gamma(const struct intel_plane_state *plane_state)
1341 {
1342         struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1343         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1344         const struct drm_framebuffer *fb = plane_state->base.fb;
1345         enum pipe pipe = plane->pipe;
1346         u16 gamma[8];
1347         int i;
1348 
1349         /* Seems RGB data bypasses the gamma always */
1350         if (!fb->format->is_yuv)
1351                 return;
1352 
1353         i9xx_plane_linear_gamma(gamma);
1354 
1355         /* FIXME these register are single buffered :( */
1356         /* The two end points are implicit (0.0 and 1.0) */
1357         for (i = 1; i < 8 - 1; i++)
1358                 I915_WRITE_FW(DVSGAMC_G4X(pipe, i - 1),
1359                               gamma[i] << 16 |
1360                               gamma[i] << 8 |
1361                               gamma[i]);
1362 }
1363 
1364 static void ilk_sprite_linear_gamma(u16 gamma[17])
1365 {
1366         int i;
1367 
1368         for (i = 0; i < 17; i++)
1369                 gamma[i] = (i << 10) / 16;
1370 }
1371 
1372 static void ilk_update_gamma(const struct intel_plane_state *plane_state)
1373 {
1374         struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1375         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1376         const struct drm_framebuffer *fb = plane_state->base.fb;
1377         enum pipe pipe = plane->pipe;
1378         u16 gamma[17];
1379         int i;
1380 
1381         /* Seems RGB data bypasses the gamma always */
1382         if (!fb->format->is_yuv)
1383                 return;
1384 
1385         ilk_sprite_linear_gamma(gamma);
1386 
1387         /* FIXME these register are single buffered :( */
1388         for (i = 0; i < 16; i++)
1389                 I915_WRITE_FW(DVSGAMC_ILK(pipe, i),
1390                               gamma[i] << 20 |
1391                               gamma[i] << 10 |
1392                               gamma[i]);
1393 
1394         I915_WRITE_FW(DVSGAMCMAX_ILK(pipe, 0), gamma[i]);
1395         I915_WRITE_FW(DVSGAMCMAX_ILK(pipe, 1), gamma[i]);
1396         I915_WRITE_FW(DVSGAMCMAX_ILK(pipe, 2), gamma[i]);
1397         i++;
1398 }
1399 
1400 static void
1401 g4x_update_plane(struct intel_plane *plane,
1402                  const struct intel_crtc_state *crtc_state,
1403                  const struct intel_plane_state *plane_state)
1404 {
1405         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1406         enum pipe pipe = plane->pipe;
1407         u32 dvssurf_offset = plane_state->color_plane[0].offset;
1408         u32 linear_offset;
1409         const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1410         int crtc_x = plane_state->base.dst.x1;
1411         int crtc_y = plane_state->base.dst.y1;
1412         u32 crtc_w = drm_rect_width(&plane_state->base.dst);
1413         u32 crtc_h = drm_rect_height(&plane_state->base.dst);
1414         u32 x = plane_state->color_plane[0].x;
1415         u32 y = plane_state->color_plane[0].y;
1416         u32 src_w = drm_rect_width(&plane_state->base.src) >> 16;
1417         u32 src_h = drm_rect_height(&plane_state->base.src) >> 16;
1418         u32 dvscntr, dvsscale = 0;
1419         unsigned long irqflags;
1420 
1421         dvscntr = plane_state->ctl | g4x_sprite_ctl_crtc(crtc_state);
1422 
1423         /* Sizes are 0 based */
1424         src_w--;
1425         src_h--;
1426         crtc_w--;
1427         crtc_h--;
1428 
1429         if (crtc_w != src_w || crtc_h != src_h)
1430                 dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
1431 
1432         linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1433 
1434         spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1435 
1436         I915_WRITE_FW(DVSSTRIDE(pipe), plane_state->color_plane[0].stride);
1437         I915_WRITE_FW(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
1438         I915_WRITE_FW(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
1439         I915_WRITE_FW(DVSSCALE(pipe), dvsscale);
1440 
1441         if (key->flags) {
1442                 I915_WRITE_FW(DVSKEYVAL(pipe), key->min_value);
1443                 I915_WRITE_FW(DVSKEYMSK(pipe), key->channel_mask);
1444                 I915_WRITE_FW(DVSKEYMAX(pipe), key->max_value);
1445         }
1446 
1447         I915_WRITE_FW(DVSLINOFF(pipe), linear_offset);
1448         I915_WRITE_FW(DVSTILEOFF(pipe), (y << 16) | x);
1449 
1450         /*
1451          * The control register self-arms if the plane was previously
1452          * disabled. Try to make the plane enable atomic by writing
1453          * the control register just before the surface register.
1454          */
1455         I915_WRITE_FW(DVSCNTR(pipe), dvscntr);
1456         I915_WRITE_FW(DVSSURF(pipe),
1457                       intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
1458 
1459         if (IS_G4X(dev_priv))
1460                 g4x_update_gamma(plane_state);
1461         else
1462                 ilk_update_gamma(plane_state);
1463 
1464         spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1465 }
1466 
1467 static void
1468 g4x_disable_plane(struct intel_plane *plane,
1469                   const struct intel_crtc_state *crtc_state)
1470 {
1471         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1472         enum pipe pipe = plane->pipe;
1473         unsigned long irqflags;
1474 
1475         spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1476 
1477         I915_WRITE_FW(DVSCNTR(pipe), 0);
1478         /* Disable the scaler */
1479         I915_WRITE_FW(DVSSCALE(pipe), 0);
1480         I915_WRITE_FW(DVSSURF(pipe), 0);
1481 
1482         spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1483 }
1484 
1485 static bool
1486 g4x_plane_get_hw_state(struct intel_plane *plane,
1487                        enum pipe *pipe)
1488 {
1489         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1490         enum intel_display_power_domain power_domain;
1491         intel_wakeref_t wakeref;
1492         bool ret;
1493 
1494         power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1495         wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1496         if (!wakeref)
1497                 return false;
1498 
1499         ret = I915_READ(DVSCNTR(plane->pipe)) & DVS_ENABLE;
1500 
1501         *pipe = plane->pipe;
1502 
1503         intel_display_power_put(dev_priv, power_domain, wakeref);
1504 
1505         return ret;
1506 }
1507 
1508 static bool intel_fb_scalable(const struct drm_framebuffer *fb)
1509 {
1510         if (!fb)
1511                 return false;
1512 
1513         switch (fb->format->format) {
1514         case DRM_FORMAT_C8:
1515                 return false;
1516         default:
1517                 return true;
1518         }
1519 }
1520 
1521 static int
1522 g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state,
1523                          struct intel_plane_state *plane_state)
1524 {
1525         const struct drm_framebuffer *fb = plane_state->base.fb;
1526         const struct drm_rect *src = &plane_state->base.src;
1527         const struct drm_rect *dst = &plane_state->base.dst;
1528         int src_x, src_w, src_h, crtc_w, crtc_h;
1529         const struct drm_display_mode *adjusted_mode =
1530                 &crtc_state->base.adjusted_mode;
1531         unsigned int stride = plane_state->color_plane[0].stride;
1532         unsigned int cpp = fb->format->cpp[0];
1533         unsigned int width_bytes;
1534         int min_width, min_height;
1535 
1536         crtc_w = drm_rect_width(dst);
1537         crtc_h = drm_rect_height(dst);
1538 
1539         src_x = src->x1 >> 16;
1540         src_w = drm_rect_width(src) >> 16;
1541         src_h = drm_rect_height(src) >> 16;
1542 
1543         if (src_w == crtc_w && src_h == crtc_h)
1544                 return 0;
1545 
1546         min_width = 3;
1547 
1548         if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
1549                 if (src_h & 1) {
1550                         DRM_DEBUG_KMS("Source height must be even with interlaced modes\n");
1551                         return -EINVAL;
1552                 }
1553                 min_height = 6;
1554         } else {
1555                 min_height = 3;
1556         }
1557 
1558         width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
1559 
1560         if (src_w < min_width || src_h < min_height ||
1561             src_w > 2048 || src_h > 2048) {
1562                 DRM_DEBUG_KMS("Source dimensions (%dx%d) exceed hardware limits (%dx%d - %dx%d)\n",
1563                               src_w, src_h, min_width, min_height, 2048, 2048);
1564                 return -EINVAL;
1565         }
1566 
1567         if (width_bytes > 4096) {
1568                 DRM_DEBUG_KMS("Fetch width (%d) exceeds hardware max with scaling (%u)\n",
1569                               width_bytes, 4096);
1570                 return -EINVAL;
1571         }
1572 
1573         if (stride > 4096) {
1574                 DRM_DEBUG_KMS("Stride (%u) exceeds hardware max with scaling (%u)\n",
1575                               stride, 4096);
1576                 return -EINVAL;
1577         }
1578 
1579         return 0;
1580 }
1581 
1582 static int
1583 g4x_sprite_check(struct intel_crtc_state *crtc_state,
1584                  struct intel_plane_state *plane_state)
1585 {
1586         struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1587         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1588         int min_scale = DRM_PLANE_HELPER_NO_SCALING;
1589         int max_scale = DRM_PLANE_HELPER_NO_SCALING;
1590         int ret;
1591 
1592         if (intel_fb_scalable(plane_state->base.fb)) {
1593                 if (INTEL_GEN(dev_priv) < 7) {
1594                         min_scale = 1;
1595                         max_scale = 16 << 16;
1596                 } else if (IS_IVYBRIDGE(dev_priv)) {
1597                         min_scale = 1;
1598                         max_scale = 2 << 16;
1599                 }
1600         }
1601 
1602         ret = drm_atomic_helper_check_plane_state(&plane_state->base,
1603                                                   &crtc_state->base,
1604                                                   min_scale, max_scale,
1605                                                   true, true);
1606         if (ret)
1607                 return ret;
1608 
1609         ret = i9xx_check_plane_surface(plane_state);
1610         if (ret)
1611                 return ret;
1612 
1613         if (!plane_state->base.visible)
1614                 return 0;
1615 
1616         ret = intel_plane_check_src_coordinates(plane_state);
1617         if (ret)
1618                 return ret;
1619 
1620         ret = g4x_sprite_check_scaling(crtc_state, plane_state);
1621         if (ret)
1622                 return ret;
1623 
1624         if (INTEL_GEN(dev_priv) >= 7)
1625                 plane_state->ctl = ivb_sprite_ctl(crtc_state, plane_state);
1626         else
1627                 plane_state->ctl = g4x_sprite_ctl(crtc_state, plane_state);
1628 
1629         return 0;
1630 }
1631 
1632 int chv_plane_check_rotation(const struct intel_plane_state *plane_state)
1633 {
1634         struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1635         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1636         unsigned int rotation = plane_state->base.rotation;
1637 
1638         /* CHV ignores the mirror bit when the rotate bit is set :( */
1639         if (IS_CHERRYVIEW(dev_priv) &&
1640             rotation & DRM_MODE_ROTATE_180 &&
1641             rotation & DRM_MODE_REFLECT_X) {
1642                 DRM_DEBUG_KMS("Cannot rotate and reflect at the same time\n");
1643                 return -EINVAL;
1644         }
1645 
1646         return 0;
1647 }
1648 
1649 static int
1650 vlv_sprite_check(struct intel_crtc_state *crtc_state,
1651                  struct intel_plane_state *plane_state)
1652 {
1653         int ret;
1654 
1655         ret = chv_plane_check_rotation(plane_state);
1656         if (ret)
1657                 return ret;
1658 
1659         ret = drm_atomic_helper_check_plane_state(&plane_state->base,
1660                                                   &crtc_state->base,
1661                                                   DRM_PLANE_HELPER_NO_SCALING,
1662                                                   DRM_PLANE_HELPER_NO_SCALING,
1663                                                   true, true);
1664         if (ret)
1665                 return ret;
1666 
1667         ret = i9xx_check_plane_surface(plane_state);
1668         if (ret)
1669                 return ret;
1670 
1671         if (!plane_state->base.visible)
1672                 return 0;
1673 
1674         ret = intel_plane_check_src_coordinates(plane_state);
1675         if (ret)
1676                 return ret;
1677 
1678         plane_state->ctl = vlv_sprite_ctl(crtc_state, plane_state);
1679 
1680         return 0;
1681 }
1682 
1683 static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
1684                               const struct intel_plane_state *plane_state)
1685 {
1686         struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1687         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1688         const struct drm_framebuffer *fb = plane_state->base.fb;
1689         unsigned int rotation = plane_state->base.rotation;
1690         struct drm_format_name_buf format_name;
1691 
1692         if (!fb)
1693                 return 0;
1694 
1695         if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) &&
1696             is_ccs_modifier(fb->modifier)) {
1697                 DRM_DEBUG_KMS("RC support only with 0/180 degree rotation (%x)\n",
1698                               rotation);
1699                 return -EINVAL;
1700         }
1701 
1702         if (rotation & DRM_MODE_REFLECT_X &&
1703             fb->modifier == DRM_FORMAT_MOD_LINEAR) {
1704                 DRM_DEBUG_KMS("horizontal flip is not supported with linear surface formats\n");
1705                 return -EINVAL;
1706         }
1707 
1708         if (drm_rotation_90_or_270(rotation)) {
1709                 if (fb->modifier != I915_FORMAT_MOD_Y_TILED &&
1710                     fb->modifier != I915_FORMAT_MOD_Yf_TILED) {
1711                         DRM_DEBUG_KMS("Y/Yf tiling required for 90/270!\n");
1712                         return -EINVAL;
1713                 }
1714 
1715                 /*
1716                  * 90/270 is not allowed with RGB64 16:16:16:16 and
1717                  * Indexed 8-bit. RGB 16-bit 5:6:5 is allowed gen11 onwards.
1718                  */
1719                 switch (fb->format->format) {
1720                 case DRM_FORMAT_RGB565:
1721                         if (INTEL_GEN(dev_priv) >= 11)
1722                                 break;
1723                         /* fall through */
1724                 case DRM_FORMAT_C8:
1725                 case DRM_FORMAT_XRGB16161616F:
1726                 case DRM_FORMAT_XBGR16161616F:
1727                 case DRM_FORMAT_ARGB16161616F:
1728                 case DRM_FORMAT_ABGR16161616F:
1729                 case DRM_FORMAT_Y210:
1730                 case DRM_FORMAT_Y212:
1731                 case DRM_FORMAT_Y216:
1732                 case DRM_FORMAT_XVYU12_16161616:
1733                 case DRM_FORMAT_XVYU16161616:
1734                         DRM_DEBUG_KMS("Unsupported pixel format %s for 90/270!\n",
1735                                       drm_get_format_name(fb->format->format,
1736                                                           &format_name));
1737                         return -EINVAL;
1738                 default:
1739                         break;
1740                 }
1741         }
1742 
1743         /* Y-tiling is not supported in IF-ID Interlace mode */
1744         if (crtc_state->base.enable &&
1745             crtc_state->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE &&
1746             (fb->modifier == I915_FORMAT_MOD_Y_TILED ||
1747              fb->modifier == I915_FORMAT_MOD_Yf_TILED ||
1748              fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
1749              fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS)) {
1750                 DRM_DEBUG_KMS("Y/Yf tiling not supported in IF-ID mode\n");
1751                 return -EINVAL;
1752         }
1753 
1754         return 0;
1755 }
1756 
1757 static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_state,
1758                                            const struct intel_plane_state *plane_state)
1759 {
1760         struct drm_i915_private *dev_priv =
1761                 to_i915(plane_state->base.plane->dev);
1762         int crtc_x = plane_state->base.dst.x1;
1763         int crtc_w = drm_rect_width(&plane_state->base.dst);
1764         int pipe_src_w = crtc_state->pipe_src_w;
1765 
1766         /*
1767          * Display WA #1175: cnl,glk
1768          * Planes other than the cursor may cause FIFO underflow and display
1769          * corruption if starting less than 4 pixels from the right edge of
1770          * the screen.
1771          * Besides the above WA fix the similar problem, where planes other
1772          * than the cursor ending less than 4 pixels from the left edge of the
1773          * screen may cause FIFO underflow and display corruption.
1774          */
1775         if ((IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) &&
1776             (crtc_x + crtc_w < 4 || crtc_x > pipe_src_w - 4)) {
1777                 DRM_DEBUG_KMS("requested plane X %s position %d invalid (valid range %d-%d)\n",
1778                               crtc_x + crtc_w < 4 ? "end" : "start",
1779                               crtc_x + crtc_w < 4 ? crtc_x + crtc_w : crtc_x,
1780                               4, pipe_src_w - 4);
1781                 return -ERANGE;
1782         }
1783 
1784         return 0;
1785 }
1786 
1787 static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_state)
1788 {
1789         const struct drm_framebuffer *fb = plane_state->base.fb;
1790         unsigned int rotation = plane_state->base.rotation;
1791         int src_w = drm_rect_width(&plane_state->base.src) >> 16;
1792 
1793         /* Display WA #1106 */
1794         if (is_planar_yuv_format(fb->format->format) && src_w & 3 &&
1795             (rotation == DRM_MODE_ROTATE_270 ||
1796              rotation == (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90))) {
1797                 DRM_DEBUG_KMS("src width must be multiple of 4 for rotated planar YUV\n");
1798                 return -EINVAL;
1799         }
1800 
1801         return 0;
1802 }
1803 
1804 static int skl_plane_check(struct intel_crtc_state *crtc_state,
1805                            struct intel_plane_state *plane_state)
1806 {
1807         struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1808         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1809         const struct drm_framebuffer *fb = plane_state->base.fb;
1810         int min_scale = DRM_PLANE_HELPER_NO_SCALING;
1811         int max_scale = DRM_PLANE_HELPER_NO_SCALING;
1812         int ret;
1813 
1814         ret = skl_plane_check_fb(crtc_state, plane_state);
1815         if (ret)
1816                 return ret;
1817 
1818         /* use scaler when colorkey is not required */
1819         if (!plane_state->ckey.flags && intel_fb_scalable(fb)) {
1820                 min_scale = 1;
1821                 max_scale = skl_max_scale(crtc_state, fb->format->format);
1822         }
1823 
1824         ret = drm_atomic_helper_check_plane_state(&plane_state->base,
1825                                                   &crtc_state->base,
1826                                                   min_scale, max_scale,
1827                                                   true, true);
1828         if (ret)
1829                 return ret;
1830 
1831         ret = skl_check_plane_surface(plane_state);
1832         if (ret)
1833                 return ret;
1834 
1835         if (!plane_state->base.visible)
1836                 return 0;
1837 
1838         ret = skl_plane_check_dst_coordinates(crtc_state, plane_state);
1839         if (ret)
1840                 return ret;
1841 
1842         ret = intel_plane_check_src_coordinates(plane_state);
1843         if (ret)
1844                 return ret;
1845 
1846         ret = skl_plane_check_nv12_rotation(plane_state);
1847         if (ret)
1848                 return ret;
1849 
1850         /* HW only has 8 bits pixel precision, disable plane if invisible */
1851         if (!(plane_state->base.alpha >> 8))
1852                 plane_state->base.visible = false;
1853 
1854         plane_state->ctl = skl_plane_ctl(crtc_state, plane_state);
1855 
1856         if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
1857                 plane_state->color_ctl = glk_plane_color_ctl(crtc_state,
1858                                                              plane_state);
1859 
1860         return 0;
1861 }
1862 
1863 static bool has_dst_key_in_primary_plane(struct drm_i915_private *dev_priv)
1864 {
1865         return INTEL_GEN(dev_priv) >= 9;
1866 }
1867 
1868 static void intel_plane_set_ckey(struct intel_plane_state *plane_state,
1869                                  const struct drm_intel_sprite_colorkey *set)
1870 {
1871         struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1872         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1873         struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1874 
1875         *key = *set;
1876 
1877         /*
1878          * We want src key enabled on the
1879          * sprite and not on the primary.
1880          */
1881         if (plane->id == PLANE_PRIMARY &&
1882             set->flags & I915_SET_COLORKEY_SOURCE)
1883                 key->flags = 0;
1884 
1885         /*
1886          * On SKL+ we want dst key enabled on
1887          * the primary and not on the sprite.
1888          */
1889         if (INTEL_GEN(dev_priv) >= 9 && plane->id != PLANE_PRIMARY &&
1890             set->flags & I915_SET_COLORKEY_DESTINATION)
1891                 key->flags = 0;
1892 }
1893 
1894 int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
1895                                     struct drm_file *file_priv)
1896 {
1897         struct drm_i915_private *dev_priv = to_i915(dev);
1898         struct drm_intel_sprite_colorkey *set = data;
1899         struct drm_plane *plane;
1900         struct drm_plane_state *plane_state;
1901         struct drm_atomic_state *state;
1902         struct drm_modeset_acquire_ctx ctx;
1903         int ret = 0;
1904 
1905         /* ignore the pointless "none" flag */
1906         set->flags &= ~I915_SET_COLORKEY_NONE;
1907 
1908         if (set->flags & ~(I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1909                 return -EINVAL;
1910 
1911         /* Make sure we don't try to enable both src & dest simultaneously */
1912         if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1913                 return -EINVAL;
1914 
1915         if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
1916             set->flags & I915_SET_COLORKEY_DESTINATION)
1917                 return -EINVAL;
1918 
1919         plane = drm_plane_find(dev, file_priv, set->plane_id);
1920         if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)
1921                 return -ENOENT;
1922 
1923         /*
1924          * SKL+ only plane 2 can do destination keying against plane 1.
1925          * Also multiple planes can't do destination keying on the same
1926          * pipe simultaneously.
1927          */
1928         if (INTEL_GEN(dev_priv) >= 9 &&
1929             to_intel_plane(plane)->id >= PLANE_SPRITE1 &&
1930             set->flags & I915_SET_COLORKEY_DESTINATION)
1931                 return -EINVAL;
1932 
1933         drm_modeset_acquire_init(&ctx, 0);
1934 
1935         state = drm_atomic_state_alloc(plane->dev);
1936         if (!state) {
1937                 ret = -ENOMEM;
1938                 goto out;
1939         }
1940         state->acquire_ctx = &ctx;
1941 
1942         while (1) {
1943                 plane_state = drm_atomic_get_plane_state(state, plane);
1944                 ret = PTR_ERR_OR_ZERO(plane_state);
1945                 if (!ret)
1946                         intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
1947 
1948                 /*
1949                  * On some platforms we have to configure
1950                  * the dst colorkey on the primary plane.
1951                  */
1952                 if (!ret && has_dst_key_in_primary_plane(dev_priv)) {
1953                         struct intel_crtc *crtc =
1954                                 intel_get_crtc_for_pipe(dev_priv,
1955                                                         to_intel_plane(plane)->pipe);
1956 
1957                         plane_state = drm_atomic_get_plane_state(state,
1958                                                                  crtc->base.primary);
1959                         ret = PTR_ERR_OR_ZERO(plane_state);
1960                         if (!ret)
1961                                 intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
1962                 }
1963 
1964                 if (!ret)
1965                         ret = drm_atomic_commit(state);
1966 
1967                 if (ret != -EDEADLK)
1968                         break;
1969 
1970                 drm_atomic_state_clear(state);
1971                 drm_modeset_backoff(&ctx);
1972         }
1973 
1974         drm_atomic_state_put(state);
1975 out:
1976         drm_modeset_drop_locks(&ctx);
1977         drm_modeset_acquire_fini(&ctx);
1978         return ret;
1979 }
1980 
1981 static const u32 g4x_plane_formats[] = {
1982         DRM_FORMAT_XRGB8888,
1983         DRM_FORMAT_YUYV,
1984         DRM_FORMAT_YVYU,
1985         DRM_FORMAT_UYVY,
1986         DRM_FORMAT_VYUY,
1987 };
1988 
1989 static const u64 i9xx_plane_format_modifiers[] = {
1990         I915_FORMAT_MOD_X_TILED,
1991         DRM_FORMAT_MOD_LINEAR,
1992         DRM_FORMAT_MOD_INVALID
1993 };
1994 
1995 static const u32 snb_plane_formats[] = {
1996         DRM_FORMAT_XBGR8888,
1997         DRM_FORMAT_XRGB8888,
1998         DRM_FORMAT_YUYV,
1999         DRM_FORMAT_YVYU,
2000         DRM_FORMAT_UYVY,
2001         DRM_FORMAT_VYUY,
2002 };
2003 
2004 static const u32 vlv_plane_formats[] = {
2005         DRM_FORMAT_RGB565,
2006         DRM_FORMAT_ABGR8888,
2007         DRM_FORMAT_ARGB8888,
2008         DRM_FORMAT_XBGR8888,
2009         DRM_FORMAT_XRGB8888,
2010         DRM_FORMAT_XBGR2101010,
2011         DRM_FORMAT_ABGR2101010,
2012         DRM_FORMAT_YUYV,
2013         DRM_FORMAT_YVYU,
2014         DRM_FORMAT_UYVY,
2015         DRM_FORMAT_VYUY,
2016 };
2017 
2018 static const u32 skl_plane_formats[] = {
2019         DRM_FORMAT_C8,
2020         DRM_FORMAT_RGB565,
2021         DRM_FORMAT_XRGB8888,
2022         DRM_FORMAT_XBGR8888,
2023         DRM_FORMAT_ARGB8888,
2024         DRM_FORMAT_ABGR8888,
2025         DRM_FORMAT_XRGB2101010,
2026         DRM_FORMAT_XBGR2101010,
2027         DRM_FORMAT_YUYV,
2028         DRM_FORMAT_YVYU,
2029         DRM_FORMAT_UYVY,
2030         DRM_FORMAT_VYUY,
2031 };
2032 
2033 static const u32 skl_planar_formats[] = {
2034         DRM_FORMAT_C8,
2035         DRM_FORMAT_RGB565,
2036         DRM_FORMAT_XRGB8888,
2037         DRM_FORMAT_XBGR8888,
2038         DRM_FORMAT_ARGB8888,
2039         DRM_FORMAT_ABGR8888,
2040         DRM_FORMAT_XRGB2101010,
2041         DRM_FORMAT_XBGR2101010,
2042         DRM_FORMAT_YUYV,
2043         DRM_FORMAT_YVYU,
2044         DRM_FORMAT_UYVY,
2045         DRM_FORMAT_VYUY,
2046         DRM_FORMAT_NV12,
2047 };
2048 
2049 static const u32 glk_planar_formats[] = {
2050         DRM_FORMAT_C8,
2051         DRM_FORMAT_RGB565,
2052         DRM_FORMAT_XRGB8888,
2053         DRM_FORMAT_XBGR8888,
2054         DRM_FORMAT_ARGB8888,
2055         DRM_FORMAT_ABGR8888,
2056         DRM_FORMAT_XRGB2101010,
2057         DRM_FORMAT_XBGR2101010,
2058         DRM_FORMAT_YUYV,
2059         DRM_FORMAT_YVYU,
2060         DRM_FORMAT_UYVY,
2061         DRM_FORMAT_VYUY,
2062         DRM_FORMAT_NV12,
2063         DRM_FORMAT_P010,
2064         DRM_FORMAT_P012,
2065         DRM_FORMAT_P016,
2066 };
2067 
2068 static const u32 icl_sdr_y_plane_formats[] = {
2069         DRM_FORMAT_C8,
2070         DRM_FORMAT_RGB565,
2071         DRM_FORMAT_XRGB8888,
2072         DRM_FORMAT_XBGR8888,
2073         DRM_FORMAT_ARGB8888,
2074         DRM_FORMAT_ABGR8888,
2075         DRM_FORMAT_XRGB2101010,
2076         DRM_FORMAT_XBGR2101010,
2077         DRM_FORMAT_YUYV,
2078         DRM_FORMAT_YVYU,
2079         DRM_FORMAT_UYVY,
2080         DRM_FORMAT_VYUY,
2081         DRM_FORMAT_Y210,
2082         DRM_FORMAT_Y212,
2083         DRM_FORMAT_Y216,
2084         DRM_FORMAT_XVYU2101010,
2085         DRM_FORMAT_XVYU12_16161616,
2086         DRM_FORMAT_XVYU16161616,
2087 };
2088 
2089 static const u32 icl_sdr_uv_plane_formats[] = {
2090         DRM_FORMAT_C8,
2091         DRM_FORMAT_RGB565,
2092         DRM_FORMAT_XRGB8888,
2093         DRM_FORMAT_XBGR8888,
2094         DRM_FORMAT_ARGB8888,
2095         DRM_FORMAT_ABGR8888,
2096         DRM_FORMAT_XRGB2101010,
2097         DRM_FORMAT_XBGR2101010,
2098         DRM_FORMAT_YUYV,
2099         DRM_FORMAT_YVYU,
2100         DRM_FORMAT_UYVY,
2101         DRM_FORMAT_VYUY,
2102         DRM_FORMAT_NV12,
2103         DRM_FORMAT_P010,
2104         DRM_FORMAT_P012,
2105         DRM_FORMAT_P016,
2106         DRM_FORMAT_Y210,
2107         DRM_FORMAT_Y212,
2108         DRM_FORMAT_Y216,
2109         DRM_FORMAT_XVYU2101010,
2110         DRM_FORMAT_XVYU12_16161616,
2111         DRM_FORMAT_XVYU16161616,
2112 };
2113 
2114 static const u32 icl_hdr_plane_formats[] = {
2115         DRM_FORMAT_C8,
2116         DRM_FORMAT_RGB565,
2117         DRM_FORMAT_XRGB8888,
2118         DRM_FORMAT_XBGR8888,
2119         DRM_FORMAT_ARGB8888,
2120         DRM_FORMAT_ABGR8888,
2121         DRM_FORMAT_XRGB2101010,
2122         DRM_FORMAT_XBGR2101010,
2123         DRM_FORMAT_XRGB16161616F,
2124         DRM_FORMAT_XBGR16161616F,
2125         DRM_FORMAT_ARGB16161616F,
2126         DRM_FORMAT_ABGR16161616F,
2127         DRM_FORMAT_YUYV,
2128         DRM_FORMAT_YVYU,
2129         DRM_FORMAT_UYVY,
2130         DRM_FORMAT_VYUY,
2131         DRM_FORMAT_NV12,
2132         DRM_FORMAT_P010,
2133         DRM_FORMAT_P012,
2134         DRM_FORMAT_P016,
2135         DRM_FORMAT_Y210,
2136         DRM_FORMAT_Y212,
2137         DRM_FORMAT_Y216,
2138         DRM_FORMAT_XVYU2101010,
2139         DRM_FORMAT_XVYU12_16161616,
2140         DRM_FORMAT_XVYU16161616,
2141 };
2142 
2143 static const u64 skl_plane_format_modifiers_noccs[] = {
2144         I915_FORMAT_MOD_Yf_TILED,
2145         I915_FORMAT_MOD_Y_TILED,
2146         I915_FORMAT_MOD_X_TILED,
2147         DRM_FORMAT_MOD_LINEAR,
2148         DRM_FORMAT_MOD_INVALID
2149 };
2150 
2151 static const u64 skl_plane_format_modifiers_ccs[] = {
2152         I915_FORMAT_MOD_Yf_TILED_CCS,
2153         I915_FORMAT_MOD_Y_TILED_CCS,
2154         I915_FORMAT_MOD_Yf_TILED,
2155         I915_FORMAT_MOD_Y_TILED,
2156         I915_FORMAT_MOD_X_TILED,
2157         DRM_FORMAT_MOD_LINEAR,
2158         DRM_FORMAT_MOD_INVALID
2159 };
2160 
2161 static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane,
2162                                             u32 format, u64 modifier)
2163 {
2164         switch (modifier) {
2165         case DRM_FORMAT_MOD_LINEAR:
2166         case I915_FORMAT_MOD_X_TILED:
2167                 break;
2168         default:
2169                 return false;
2170         }
2171 
2172         switch (format) {
2173         case DRM_FORMAT_XRGB8888:
2174         case DRM_FORMAT_YUYV:
2175         case DRM_FORMAT_YVYU:
2176         case DRM_FORMAT_UYVY:
2177         case DRM_FORMAT_VYUY:
2178                 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2179                     modifier == I915_FORMAT_MOD_X_TILED)
2180                         return true;
2181                 /* fall through */
2182         default:
2183                 return false;
2184         }
2185 }
2186 
2187 static bool snb_sprite_format_mod_supported(struct drm_plane *_plane,
2188                                             u32 format, u64 modifier)
2189 {
2190         switch (modifier) {
2191         case DRM_FORMAT_MOD_LINEAR:
2192         case I915_FORMAT_MOD_X_TILED:
2193                 break;
2194         default:
2195                 return false;
2196         }
2197 
2198         switch (format) {
2199         case DRM_FORMAT_XRGB8888:
2200         case DRM_FORMAT_XBGR8888:
2201         case DRM_FORMAT_YUYV:
2202         case DRM_FORMAT_YVYU:
2203         case DRM_FORMAT_UYVY:
2204         case DRM_FORMAT_VYUY:
2205                 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2206                     modifier == I915_FORMAT_MOD_X_TILED)
2207                         return true;
2208                 /* fall through */
2209         default:
2210                 return false;
2211         }
2212 }
2213 
2214 static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane,
2215                                             u32 format, u64 modifier)
2216 {
2217         switch (modifier) {
2218         case DRM_FORMAT_MOD_LINEAR:
2219         case I915_FORMAT_MOD_X_TILED:
2220                 break;
2221         default:
2222                 return false;
2223         }
2224 
2225         switch (format) {
2226         case DRM_FORMAT_RGB565:
2227         case DRM_FORMAT_ABGR8888:
2228         case DRM_FORMAT_ARGB8888:
2229         case DRM_FORMAT_XBGR8888:
2230         case DRM_FORMAT_XRGB8888:
2231         case DRM_FORMAT_XBGR2101010:
2232         case DRM_FORMAT_ABGR2101010:
2233         case DRM_FORMAT_YUYV:
2234         case DRM_FORMAT_YVYU:
2235         case DRM_FORMAT_UYVY:
2236         case DRM_FORMAT_VYUY:
2237                 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2238                     modifier == I915_FORMAT_MOD_X_TILED)
2239                         return true;
2240                 /* fall through */
2241         default:
2242                 return false;
2243         }
2244 }
2245 
2246 static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
2247                                            u32 format, u64 modifier)
2248 {
2249         struct intel_plane *plane = to_intel_plane(_plane);
2250 
2251         switch (modifier) {
2252         case DRM_FORMAT_MOD_LINEAR:
2253         case I915_FORMAT_MOD_X_TILED:
2254         case I915_FORMAT_MOD_Y_TILED:
2255         case I915_FORMAT_MOD_Yf_TILED:
2256                 break;
2257         case I915_FORMAT_MOD_Y_TILED_CCS:
2258         case I915_FORMAT_MOD_Yf_TILED_CCS:
2259                 if (!plane->has_ccs)
2260                         return false;
2261                 break;
2262         default:
2263                 return false;
2264         }
2265 
2266         switch (format) {
2267         case DRM_FORMAT_XRGB8888:
2268         case DRM_FORMAT_XBGR8888:
2269         case DRM_FORMAT_ARGB8888:
2270         case DRM_FORMAT_ABGR8888:
2271                 if (is_ccs_modifier(modifier))
2272                         return true;
2273                 /* fall through */
2274         case DRM_FORMAT_RGB565:
2275         case DRM_FORMAT_XRGB2101010:
2276         case DRM_FORMAT_XBGR2101010:
2277         case DRM_FORMAT_YUYV:
2278         case DRM_FORMAT_YVYU:
2279         case DRM_FORMAT_UYVY:
2280         case DRM_FORMAT_VYUY:
2281         case DRM_FORMAT_NV12:
2282         case DRM_FORMAT_P010:
2283         case DRM_FORMAT_P012:
2284         case DRM_FORMAT_P016:
2285         case DRM_FORMAT_XVYU2101010:
2286                 if (modifier == I915_FORMAT_MOD_Yf_TILED)
2287                         return true;
2288                 /* fall through */
2289         case DRM_FORMAT_C8:
2290         case DRM_FORMAT_XBGR16161616F:
2291         case DRM_FORMAT_ABGR16161616F:
2292         case DRM_FORMAT_XRGB16161616F:
2293         case DRM_FORMAT_ARGB16161616F:
2294         case DRM_FORMAT_Y210:
2295         case DRM_FORMAT_Y212:
2296         case DRM_FORMAT_Y216:
2297         case DRM_FORMAT_XVYU12_16161616:
2298         case DRM_FORMAT_XVYU16161616:
2299                 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2300                     modifier == I915_FORMAT_MOD_X_TILED ||
2301                     modifier == I915_FORMAT_MOD_Y_TILED)
2302                         return true;
2303                 /* fall through */
2304         default:
2305                 return false;
2306         }
2307 }
2308 
2309 static const struct drm_plane_funcs g4x_sprite_funcs = {
2310         .update_plane = drm_atomic_helper_update_plane,
2311         .disable_plane = drm_atomic_helper_disable_plane,
2312         .destroy = intel_plane_destroy,
2313         .atomic_duplicate_state = intel_plane_duplicate_state,
2314         .atomic_destroy_state = intel_plane_destroy_state,
2315         .format_mod_supported = g4x_sprite_format_mod_supported,
2316 };
2317 
2318 static const struct drm_plane_funcs snb_sprite_funcs = {
2319         .update_plane = drm_atomic_helper_update_plane,
2320         .disable_plane = drm_atomic_helper_disable_plane,
2321         .destroy = intel_plane_destroy,
2322         .atomic_duplicate_state = intel_plane_duplicate_state,
2323         .atomic_destroy_state = intel_plane_destroy_state,
2324         .format_mod_supported = snb_sprite_format_mod_supported,
2325 };
2326 
2327 static const struct drm_plane_funcs vlv_sprite_funcs = {
2328         .update_plane = drm_atomic_helper_update_plane,
2329         .disable_plane = drm_atomic_helper_disable_plane,
2330         .destroy = intel_plane_destroy,
2331         .atomic_duplicate_state = intel_plane_duplicate_state,
2332         .atomic_destroy_state = intel_plane_destroy_state,
2333         .format_mod_supported = vlv_sprite_format_mod_supported,
2334 };
2335 
2336 static const struct drm_plane_funcs skl_plane_funcs = {
2337         .update_plane = drm_atomic_helper_update_plane,
2338         .disable_plane = drm_atomic_helper_disable_plane,
2339         .destroy = intel_plane_destroy,
2340         .atomic_duplicate_state = intel_plane_duplicate_state,
2341         .atomic_destroy_state = intel_plane_destroy_state,
2342         .format_mod_supported = skl_plane_format_mod_supported,
2343 };
2344 
2345 static bool skl_plane_has_fbc(struct drm_i915_private *dev_priv,
2346                               enum pipe pipe, enum plane_id plane_id)
2347 {
2348         if (!HAS_FBC(dev_priv))
2349                 return false;
2350 
2351         return pipe == PIPE_A && plane_id == PLANE_PRIMARY;
2352 }
2353 
2354 static bool skl_plane_has_planar(struct drm_i915_private *dev_priv,
2355                                  enum pipe pipe, enum plane_id plane_id)
2356 {
2357         /* Display WA #0870: skl, bxt */
2358         if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))
2359                 return false;
2360 
2361         if (IS_GEN(dev_priv, 9) && !IS_GEMINILAKE(dev_priv) && pipe == PIPE_C)
2362                 return false;
2363 
2364         if (plane_id != PLANE_PRIMARY && plane_id != PLANE_SPRITE0)
2365                 return false;
2366 
2367         return true;
2368 }
2369 
2370 static const u32 *skl_get_plane_formats(struct drm_i915_private *dev_priv,
2371                                         enum pipe pipe, enum plane_id plane_id,
2372                                         int *num_formats)
2373 {
2374         if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
2375                 *num_formats = ARRAY_SIZE(skl_planar_formats);
2376                 return skl_planar_formats;
2377         } else {
2378                 *num_formats = ARRAY_SIZE(skl_plane_formats);
2379                 return skl_plane_formats;
2380         }
2381 }
2382 
2383 static const u32 *glk_get_plane_formats(struct drm_i915_private *dev_priv,
2384                                         enum pipe pipe, enum plane_id plane_id,
2385                                         int *num_formats)
2386 {
2387         if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
2388                 *num_formats = ARRAY_SIZE(glk_planar_formats);
2389                 return glk_planar_formats;
2390         } else {
2391                 *num_formats = ARRAY_SIZE(skl_plane_formats);
2392                 return skl_plane_formats;
2393         }
2394 }
2395 
2396 static const u32 *icl_get_plane_formats(struct drm_i915_private *dev_priv,
2397                                         enum pipe pipe, enum plane_id plane_id,
2398                                         int *num_formats)
2399 {
2400         if (icl_is_hdr_plane(dev_priv, plane_id)) {
2401                 *num_formats = ARRAY_SIZE(icl_hdr_plane_formats);
2402                 return icl_hdr_plane_formats;
2403         } else if (icl_is_nv12_y_plane(plane_id)) {
2404                 *num_formats = ARRAY_SIZE(icl_sdr_y_plane_formats);
2405                 return icl_sdr_y_plane_formats;
2406         } else {
2407                 *num_formats = ARRAY_SIZE(icl_sdr_uv_plane_formats);
2408                 return icl_sdr_uv_plane_formats;
2409         }
2410 }
2411 
2412 static bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
2413                               enum pipe pipe, enum plane_id plane_id)
2414 {
2415         if (plane_id == PLANE_CURSOR)
2416                 return false;
2417 
2418         if (INTEL_GEN(dev_priv) >= 10)
2419                 return true;
2420 
2421         if (IS_GEMINILAKE(dev_priv))
2422                 return pipe != PIPE_C;
2423 
2424         return pipe != PIPE_C &&
2425                 (plane_id == PLANE_PRIMARY ||
2426                  plane_id == PLANE_SPRITE0);
2427 }
2428 
2429 struct intel_plane *
2430 skl_universal_plane_create(struct drm_i915_private *dev_priv,
2431                            enum pipe pipe, enum plane_id plane_id)
2432 {
2433         struct intel_plane *plane;
2434         enum drm_plane_type plane_type;
2435         unsigned int supported_rotations;
2436         unsigned int possible_crtcs;
2437         const u64 *modifiers;
2438         const u32 *formats;
2439         int num_formats;
2440         int ret;
2441 
2442         plane = intel_plane_alloc();
2443         if (IS_ERR(plane))
2444                 return plane;
2445 
2446         plane->pipe = pipe;
2447         plane->id = plane_id;
2448         plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane_id);
2449 
2450         plane->has_fbc = skl_plane_has_fbc(dev_priv, pipe, plane_id);
2451         if (plane->has_fbc) {
2452                 struct intel_fbc *fbc = &dev_priv->fbc;
2453 
2454                 fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
2455         }
2456 
2457         plane->max_stride = skl_plane_max_stride;
2458         plane->update_plane = skl_update_plane;
2459         plane->disable_plane = skl_disable_plane;
2460         plane->get_hw_state = skl_plane_get_hw_state;
2461         plane->check_plane = skl_plane_check;
2462         if (icl_is_nv12_y_plane(plane_id))
2463                 plane->update_slave = icl_update_slave;
2464 
2465         if (INTEL_GEN(dev_priv) >= 11)
2466                 formats = icl_get_plane_formats(dev_priv, pipe,
2467                                                 plane_id, &num_formats);
2468         else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
2469                 formats = glk_get_plane_formats(dev_priv, pipe,
2470                                                 plane_id, &num_formats);
2471         else
2472                 formats = skl_get_plane_formats(dev_priv, pipe,
2473                                                 plane_id, &num_formats);
2474 
2475         plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, plane_id);
2476         if (plane->has_ccs)
2477                 modifiers = skl_plane_format_modifiers_ccs;
2478         else
2479                 modifiers = skl_plane_format_modifiers_noccs;
2480 
2481         if (plane_id == PLANE_PRIMARY)
2482                 plane_type = DRM_PLANE_TYPE_PRIMARY;
2483         else
2484                 plane_type = DRM_PLANE_TYPE_OVERLAY;
2485 
2486         possible_crtcs = BIT(pipe);
2487 
2488         ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
2489                                        possible_crtcs, &skl_plane_funcs,
2490                                        formats, num_formats, modifiers,
2491                                        plane_type,
2492                                        "plane %d%c", plane_id + 1,
2493                                        pipe_name(pipe));
2494         if (ret)
2495                 goto fail;
2496 
2497         supported_rotations =
2498                 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
2499                 DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
2500 
2501         if (INTEL_GEN(dev_priv) >= 10)
2502                 supported_rotations |= DRM_MODE_REFLECT_X;
2503 
2504         drm_plane_create_rotation_property(&plane->base,
2505                                            DRM_MODE_ROTATE_0,
2506                                            supported_rotations);
2507 
2508         drm_plane_create_color_properties(&plane->base,
2509                                           BIT(DRM_COLOR_YCBCR_BT601) |
2510                                           BIT(DRM_COLOR_YCBCR_BT709),
2511                                           BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
2512                                           BIT(DRM_COLOR_YCBCR_FULL_RANGE),
2513                                           DRM_COLOR_YCBCR_BT709,
2514                                           DRM_COLOR_YCBCR_LIMITED_RANGE);
2515 
2516         drm_plane_create_alpha_property(&plane->base);
2517         drm_plane_create_blend_mode_property(&plane->base,
2518                                              BIT(DRM_MODE_BLEND_PIXEL_NONE) |
2519                                              BIT(DRM_MODE_BLEND_PREMULTI) |
2520                                              BIT(DRM_MODE_BLEND_COVERAGE));
2521 
2522         drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
2523 
2524         return plane;
2525 
2526 fail:
2527         intel_plane_free(plane);
2528 
2529         return ERR_PTR(ret);
2530 }
2531 
2532 struct intel_plane *
2533 intel_sprite_plane_create(struct drm_i915_private *dev_priv,
2534                           enum pipe pipe, int sprite)
2535 {
2536         struct intel_plane *plane;
2537         const struct drm_plane_funcs *plane_funcs;
2538         unsigned long possible_crtcs;
2539         unsigned int supported_rotations;
2540         const u64 *modifiers;
2541         const u32 *formats;
2542         int num_formats;
2543         int ret;
2544 
2545         if (INTEL_GEN(dev_priv) >= 9)
2546                 return skl_universal_plane_create(dev_priv, pipe,
2547                                                   PLANE_SPRITE0 + sprite);
2548 
2549         plane = intel_plane_alloc();
2550         if (IS_ERR(plane))
2551                 return plane;
2552 
2553         if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
2554                 plane->max_stride = i9xx_plane_max_stride;
2555                 plane->update_plane = vlv_update_plane;
2556                 plane->disable_plane = vlv_disable_plane;
2557                 plane->get_hw_state = vlv_plane_get_hw_state;
2558                 plane->check_plane = vlv_sprite_check;
2559 
2560                 formats = vlv_plane_formats;
2561                 num_formats = ARRAY_SIZE(vlv_plane_formats);
2562                 modifiers = i9xx_plane_format_modifiers;
2563 
2564                 plane_funcs = &vlv_sprite_funcs;
2565         } else if (INTEL_GEN(dev_priv) >= 7) {
2566                 plane->max_stride = g4x_sprite_max_stride;
2567                 plane->update_plane = ivb_update_plane;
2568                 plane->disable_plane = ivb_disable_plane;
2569                 plane->get_hw_state = ivb_plane_get_hw_state;
2570                 plane->check_plane = g4x_sprite_check;
2571 
2572                 formats = snb_plane_formats;
2573                 num_formats = ARRAY_SIZE(snb_plane_formats);
2574                 modifiers = i9xx_plane_format_modifiers;
2575 
2576                 plane_funcs = &snb_sprite_funcs;
2577         } else {
2578                 plane->max_stride = g4x_sprite_max_stride;
2579                 plane->update_plane = g4x_update_plane;
2580                 plane->disable_plane = g4x_disable_plane;
2581                 plane->get_hw_state = g4x_plane_get_hw_state;
2582                 plane->check_plane = g4x_sprite_check;
2583 
2584                 modifiers = i9xx_plane_format_modifiers;
2585                 if (IS_GEN(dev_priv, 6)) {
2586                         formats = snb_plane_formats;
2587                         num_formats = ARRAY_SIZE(snb_plane_formats);
2588 
2589                         plane_funcs = &snb_sprite_funcs;
2590                 } else {
2591                         formats = g4x_plane_formats;
2592                         num_formats = ARRAY_SIZE(g4x_plane_formats);
2593 
2594                         plane_funcs = &g4x_sprite_funcs;
2595                 }
2596         }
2597 
2598         if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
2599                 supported_rotations =
2600                         DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
2601                         DRM_MODE_REFLECT_X;
2602         } else {
2603                 supported_rotations =
2604                         DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
2605         }
2606 
2607         plane->pipe = pipe;
2608         plane->id = PLANE_SPRITE0 + sprite;
2609         plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
2610 
2611         possible_crtcs = BIT(pipe);
2612 
2613         ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
2614                                        possible_crtcs, plane_funcs,
2615                                        formats, num_formats, modifiers,
2616                                        DRM_PLANE_TYPE_OVERLAY,
2617                                        "sprite %c", sprite_name(pipe, sprite));
2618         if (ret)
2619                 goto fail;
2620 
2621         drm_plane_create_rotation_property(&plane->base,
2622                                            DRM_MODE_ROTATE_0,
2623                                            supported_rotations);
2624 
2625         drm_plane_create_color_properties(&plane->base,
2626                                           BIT(DRM_COLOR_YCBCR_BT601) |
2627                                           BIT(DRM_COLOR_YCBCR_BT709),
2628                                           BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
2629                                           BIT(DRM_COLOR_YCBCR_FULL_RANGE),
2630                                           DRM_COLOR_YCBCR_BT709,
2631                                           DRM_COLOR_YCBCR_LIMITED_RANGE);
2632 
2633         drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
2634 
2635         return plane;
2636 
2637 fail:
2638         intel_plane_free(plane);
2639 
2640         return ERR_PTR(ret);
2641 }

/* [<][>][^][v][top][bottom][index][help] */