0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 #include <linux/string_helpers.h>
0034
0035 #include <drm/drm_atomic.h>
0036 #include <drm/drm_atomic_helper.h>
0037 #include <drm/drm_blend.h>
0038 #include <drm/drm_color_mgmt.h>
0039 #include <drm/drm_crtc.h>
0040 #include <drm/drm_damage_helper.h>
0041 #include <drm/drm_fourcc.h>
0042 #include <drm/drm_plane_helper.h>
0043 #include <drm/drm_rect.h>
0044
0045 #include "i915_drv.h"
0046 #include "i915_vgpu.h"
0047 #include "i9xx_plane.h"
0048 #include "intel_atomic_plane.h"
0049 #include "intel_crtc.h"
0050 #include "intel_de.h"
0051 #include "intel_display_types.h"
0052 #include "intel_fb.h"
0053 #include "intel_frontbuffer.h"
0054 #include "intel_sprite.h"
0055 #include "intel_vrr.h"
0056
0057 int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
0058 {
0059 struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
0060 const struct drm_framebuffer *fb = plane_state->hw.fb;
0061 struct drm_rect *src = &plane_state->uapi.src;
0062 u32 src_x, src_y, src_w, src_h, hsub, vsub;
0063 bool rotated = drm_rotation_90_or_270(plane_state->hw.rotation);
0064
0065
0066
0067
0068
0069
0070
0071 if (fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
0072 fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS)
0073 return 0;
0074
0075
0076
0077
0078
0079
0080
0081 src_x = src->x1 >> 16;
0082 src_w = drm_rect_width(src) >> 16;
0083 src_y = src->y1 >> 16;
0084 src_h = drm_rect_height(src) >> 16;
0085
0086 drm_rect_init(src, src_x << 16, src_y << 16,
0087 src_w << 16, src_h << 16);
0088
0089 if (fb->format->format == DRM_FORMAT_RGB565 && rotated) {
0090 hsub = 2;
0091 vsub = 2;
0092 } else {
0093 hsub = fb->format->hsub;
0094 vsub = fb->format->vsub;
0095 }
0096
0097 if (rotated)
0098 hsub = vsub = max(hsub, vsub);
0099
0100 if (src_x % hsub || src_w % hsub) {
0101 drm_dbg_kms(&i915->drm, "src x/w (%u, %u) must be a multiple of %u (rotated: %s)\n",
0102 src_x, src_w, hsub, str_yes_no(rotated));
0103 return -EINVAL;
0104 }
0105
0106 if (src_y % vsub || src_h % vsub) {
0107 drm_dbg_kms(&i915->drm, "src y/h (%u, %u) must be a multiple of %u (rotated: %s)\n",
0108 src_y, src_h, vsub, str_yes_no(rotated));
0109 return -EINVAL;
0110 }
0111
0112 return 0;
0113 }
0114
0115 static void i9xx_plane_linear_gamma(u16 gamma[8])
0116 {
0117
0118 static const u8 in[8] = { 0, 1, 2, 4, 8, 16, 24, 32 };
0119 int i;
0120
0121 for (i = 0; i < 8; i++)
0122 gamma[i] = (in[i] << 8) / 32;
0123 }
0124
0125 static void
0126 chv_sprite_update_csc(const struct intel_plane_state *plane_state)
0127 {
0128 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
0129 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0130 const struct drm_framebuffer *fb = plane_state->hw.fb;
0131 enum plane_id plane_id = plane->id;
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142 static const s16 csc_matrix[][9] = {
0143
0144 [DRM_COLOR_YCBCR_BT601] = {
0145 5743, 4096, 0,
0146 -2925, 4096, -1410,
0147 0, 4096, 7258,
0148 },
0149
0150 [DRM_COLOR_YCBCR_BT709] = {
0151 6450, 4096, 0,
0152 -1917, 4096, -767,
0153 0, 4096, 7601,
0154 },
0155 };
0156 const s16 *csc = csc_matrix[plane_state->hw.color_encoding];
0157
0158
0159 if (!fb->format->is_yuv)
0160 return;
0161
0162 intel_de_write_fw(dev_priv, SPCSCYGOFF(plane_id),
0163 SPCSC_OOFF(0) | SPCSC_IOFF(0));
0164 intel_de_write_fw(dev_priv, SPCSCCBOFF(plane_id),
0165 SPCSC_OOFF(0) | SPCSC_IOFF(0));
0166 intel_de_write_fw(dev_priv, SPCSCCROFF(plane_id),
0167 SPCSC_OOFF(0) | SPCSC_IOFF(0));
0168
0169 intel_de_write_fw(dev_priv, SPCSCC01(plane_id),
0170 SPCSC_C1(csc[1]) | SPCSC_C0(csc[0]));
0171 intel_de_write_fw(dev_priv, SPCSCC23(plane_id),
0172 SPCSC_C1(csc[3]) | SPCSC_C0(csc[2]));
0173 intel_de_write_fw(dev_priv, SPCSCC45(plane_id),
0174 SPCSC_C1(csc[5]) | SPCSC_C0(csc[4]));
0175 intel_de_write_fw(dev_priv, SPCSCC67(plane_id),
0176 SPCSC_C1(csc[7]) | SPCSC_C0(csc[6]));
0177 intel_de_write_fw(dev_priv, SPCSCC8(plane_id), SPCSC_C0(csc[8]));
0178
0179 intel_de_write_fw(dev_priv, SPCSCYGICLAMP(plane_id),
0180 SPCSC_IMAX(1023) | SPCSC_IMIN(0));
0181 intel_de_write_fw(dev_priv, SPCSCCBICLAMP(plane_id),
0182 SPCSC_IMAX(512) | SPCSC_IMIN(-512));
0183 intel_de_write_fw(dev_priv, SPCSCCRICLAMP(plane_id),
0184 SPCSC_IMAX(512) | SPCSC_IMIN(-512));
0185
0186 intel_de_write_fw(dev_priv, SPCSCYGOCLAMP(plane_id),
0187 SPCSC_OMAX(1023) | SPCSC_OMIN(0));
0188 intel_de_write_fw(dev_priv, SPCSCCBOCLAMP(plane_id),
0189 SPCSC_OMAX(1023) | SPCSC_OMIN(0));
0190 intel_de_write_fw(dev_priv, SPCSCCROCLAMP(plane_id),
0191 SPCSC_OMAX(1023) | SPCSC_OMIN(0));
0192 }
0193
0194 #define SIN_0 0
0195 #define COS_0 1
0196
0197 static void
0198 vlv_sprite_update_clrc(const struct intel_plane_state *plane_state)
0199 {
0200 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
0201 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0202 const struct drm_framebuffer *fb = plane_state->hw.fb;
0203 enum pipe pipe = plane->pipe;
0204 enum plane_id plane_id = plane->id;
0205 int contrast, brightness, sh_scale, sh_sin, sh_cos;
0206
0207 if (fb->format->is_yuv &&
0208 plane_state->hw.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) {
0209
0210
0211
0212
0213
0214
0215 contrast = DIV_ROUND_CLOSEST(255 << 6, 235 - 16);
0216 brightness = -DIV_ROUND_CLOSEST(16 * 255, 235 - 16);
0217 sh_scale = DIV_ROUND_CLOSEST(128 << 7, 240 - 128);
0218 sh_sin = SIN_0 * sh_scale;
0219 sh_cos = COS_0 * sh_scale;
0220 } else {
0221
0222 contrast = 1 << 6;
0223 brightness = 0;
0224 sh_scale = 1 << 7;
0225 sh_sin = SIN_0 * sh_scale;
0226 sh_cos = COS_0 * sh_scale;
0227 }
0228
0229
0230 intel_de_write_fw(dev_priv, SPCLRC0(pipe, plane_id),
0231 SP_CONTRAST(contrast) | SP_BRIGHTNESS(brightness));
0232 intel_de_write_fw(dev_priv, SPCLRC1(pipe, plane_id),
0233 SP_SH_SIN(sh_sin) | SP_SH_COS(sh_cos));
0234 }
0235
0236 static void
0237 vlv_plane_ratio(const struct intel_crtc_state *crtc_state,
0238 const struct intel_plane_state *plane_state,
0239 unsigned int *num, unsigned int *den)
0240 {
0241 u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
0242 const struct drm_framebuffer *fb = plane_state->hw.fb;
0243 unsigned int cpp = fb->format->cpp[0];
0244
0245
0246
0247
0248
0249
0250
0251 if (hweight8(active_planes) == 3) {
0252 switch (cpp) {
0253 case 8:
0254 *num = 11;
0255 *den = 8;
0256 break;
0257 case 4:
0258 *num = 18;
0259 *den = 16;
0260 break;
0261 default:
0262 *num = 1;
0263 *den = 1;
0264 break;
0265 }
0266 } else if (hweight8(active_planes) == 2) {
0267 switch (cpp) {
0268 case 8:
0269 *num = 10;
0270 *den = 8;
0271 break;
0272 case 4:
0273 *num = 17;
0274 *den = 16;
0275 break;
0276 default:
0277 *num = 1;
0278 *den = 1;
0279 break;
0280 }
0281 } else {
0282 switch (cpp) {
0283 case 8:
0284 *num = 10;
0285 *den = 8;
0286 break;
0287 default:
0288 *num = 1;
0289 *den = 1;
0290 break;
0291 }
0292 }
0293 }
0294
0295 int vlv_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
0296 const struct intel_plane_state *plane_state)
0297 {
0298 unsigned int pixel_rate;
0299 unsigned int num, den;
0300
0301
0302
0303
0304
0305
0306
0307
0308 pixel_rate = crtc_state->pixel_rate;
0309
0310 vlv_plane_ratio(crtc_state, plane_state, &num, &den);
0311
0312 return DIV_ROUND_UP(pixel_rate * num, den);
0313 }
0314
0315 static u32 vlv_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
0316 {
0317 u32 sprctl = 0;
0318
0319 if (crtc_state->gamma_enable)
0320 sprctl |= SP_PIPE_GAMMA_ENABLE;
0321
0322 return sprctl;
0323 }
0324
0325 static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
0326 const struct intel_plane_state *plane_state)
0327 {
0328 const struct drm_framebuffer *fb = plane_state->hw.fb;
0329 unsigned int rotation = plane_state->hw.rotation;
0330 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
0331 u32 sprctl;
0332
0333 sprctl = SP_ENABLE;
0334
0335 switch (fb->format->format) {
0336 case DRM_FORMAT_YUYV:
0337 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
0338 break;
0339 case DRM_FORMAT_YVYU:
0340 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
0341 break;
0342 case DRM_FORMAT_UYVY:
0343 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
0344 break;
0345 case DRM_FORMAT_VYUY:
0346 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
0347 break;
0348 case DRM_FORMAT_C8:
0349 sprctl |= SP_FORMAT_8BPP;
0350 break;
0351 case DRM_FORMAT_RGB565:
0352 sprctl |= SP_FORMAT_BGR565;
0353 break;
0354 case DRM_FORMAT_XRGB8888:
0355 sprctl |= SP_FORMAT_BGRX8888;
0356 break;
0357 case DRM_FORMAT_ARGB8888:
0358 sprctl |= SP_FORMAT_BGRA8888;
0359 break;
0360 case DRM_FORMAT_XBGR2101010:
0361 sprctl |= SP_FORMAT_RGBX1010102;
0362 break;
0363 case DRM_FORMAT_ABGR2101010:
0364 sprctl |= SP_FORMAT_RGBA1010102;
0365 break;
0366 case DRM_FORMAT_XRGB2101010:
0367 sprctl |= SP_FORMAT_BGRX1010102;
0368 break;
0369 case DRM_FORMAT_ARGB2101010:
0370 sprctl |= SP_FORMAT_BGRA1010102;
0371 break;
0372 case DRM_FORMAT_XBGR8888:
0373 sprctl |= SP_FORMAT_RGBX8888;
0374 break;
0375 case DRM_FORMAT_ABGR8888:
0376 sprctl |= SP_FORMAT_RGBA8888;
0377 break;
0378 default:
0379 MISSING_CASE(fb->format->format);
0380 return 0;
0381 }
0382
0383 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
0384 sprctl |= SP_YUV_FORMAT_BT709;
0385
0386 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
0387 sprctl |= SP_TILED;
0388
0389 if (rotation & DRM_MODE_ROTATE_180)
0390 sprctl |= SP_ROTATE_180;
0391
0392 if (rotation & DRM_MODE_REFLECT_X)
0393 sprctl |= SP_MIRROR;
0394
0395 if (key->flags & I915_SET_COLORKEY_SOURCE)
0396 sprctl |= SP_SOURCE_KEY;
0397
0398 return sprctl;
0399 }
0400
0401 static void vlv_sprite_update_gamma(const struct intel_plane_state *plane_state)
0402 {
0403 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
0404 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0405 const struct drm_framebuffer *fb = plane_state->hw.fb;
0406 enum pipe pipe = plane->pipe;
0407 enum plane_id plane_id = plane->id;
0408 u16 gamma[8];
0409 int i;
0410
0411
0412 if (!fb->format->is_yuv)
0413 return;
0414
0415 i9xx_plane_linear_gamma(gamma);
0416
0417
0418
0419 for (i = 1; i < 8 - 1; i++)
0420 intel_de_write_fw(dev_priv, SPGAMC(pipe, plane_id, i - 1),
0421 gamma[i] << 16 | gamma[i] << 8 | gamma[i]);
0422 }
0423
0424 static void
0425 vlv_sprite_update_noarm(struct intel_plane *plane,
0426 const struct intel_crtc_state *crtc_state,
0427 const struct intel_plane_state *plane_state)
0428 {
0429 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0430 enum pipe pipe = plane->pipe;
0431 enum plane_id plane_id = plane->id;
0432 int crtc_x = plane_state->uapi.dst.x1;
0433 int crtc_y = plane_state->uapi.dst.y1;
0434 u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
0435 u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
0436
0437 intel_de_write_fw(dev_priv, SPSTRIDE(pipe, plane_id),
0438 plane_state->view.color_plane[0].mapping_stride);
0439 intel_de_write_fw(dev_priv, SPPOS(pipe, plane_id),
0440 SP_POS_Y(crtc_y) | SP_POS_X(crtc_x));
0441 intel_de_write_fw(dev_priv, SPSIZE(pipe, plane_id),
0442 SP_HEIGHT(crtc_h - 1) | SP_WIDTH(crtc_w - 1));
0443 }
0444
0445 static void
0446 vlv_sprite_update_arm(struct intel_plane *plane,
0447 const struct intel_crtc_state *crtc_state,
0448 const struct intel_plane_state *plane_state)
0449 {
0450 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0451 enum pipe pipe = plane->pipe;
0452 enum plane_id plane_id = plane->id;
0453 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
0454 u32 sprsurf_offset = plane_state->view.color_plane[0].offset;
0455 u32 x = plane_state->view.color_plane[0].x;
0456 u32 y = plane_state->view.color_plane[0].y;
0457 u32 sprctl, linear_offset;
0458
0459 sprctl = plane_state->ctl | vlv_sprite_ctl_crtc(crtc_state);
0460
0461 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
0462
0463 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
0464 chv_sprite_update_csc(plane_state);
0465
0466 if (key->flags) {
0467 intel_de_write_fw(dev_priv, SPKEYMINVAL(pipe, plane_id),
0468 key->min_value);
0469 intel_de_write_fw(dev_priv, SPKEYMSK(pipe, plane_id),
0470 key->channel_mask);
0471 intel_de_write_fw(dev_priv, SPKEYMAXVAL(pipe, plane_id),
0472 key->max_value);
0473 }
0474
0475 intel_de_write_fw(dev_priv, SPCONSTALPHA(pipe, plane_id), 0);
0476
0477 intel_de_write_fw(dev_priv, SPLINOFF(pipe, plane_id), linear_offset);
0478 intel_de_write_fw(dev_priv, SPTILEOFF(pipe, plane_id),
0479 SP_OFFSET_Y(y) | SP_OFFSET_X(x));
0480
0481
0482
0483
0484
0485
0486 intel_de_write_fw(dev_priv, SPCNTR(pipe, plane_id), sprctl);
0487 intel_de_write_fw(dev_priv, SPSURF(pipe, plane_id),
0488 intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
0489
0490 vlv_sprite_update_clrc(plane_state);
0491 vlv_sprite_update_gamma(plane_state);
0492 }
0493
0494 static void
0495 vlv_sprite_disable_arm(struct intel_plane *plane,
0496 const struct intel_crtc_state *crtc_state)
0497 {
0498 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0499 enum pipe pipe = plane->pipe;
0500 enum plane_id plane_id = plane->id;
0501
0502 intel_de_write_fw(dev_priv, SPCNTR(pipe, plane_id), 0);
0503 intel_de_write_fw(dev_priv, SPSURF(pipe, plane_id), 0);
0504 }
0505
0506 static bool
0507 vlv_sprite_get_hw_state(struct intel_plane *plane,
0508 enum pipe *pipe)
0509 {
0510 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0511 enum intel_display_power_domain power_domain;
0512 enum plane_id plane_id = plane->id;
0513 intel_wakeref_t wakeref;
0514 bool ret;
0515
0516 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
0517 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
0518 if (!wakeref)
0519 return false;
0520
0521 ret = intel_de_read(dev_priv, SPCNTR(plane->pipe, plane_id)) & SP_ENABLE;
0522
0523 *pipe = plane->pipe;
0524
0525 intel_display_power_put(dev_priv, power_domain, wakeref);
0526
0527 return ret;
0528 }
0529
0530 static void ivb_plane_ratio(const struct intel_crtc_state *crtc_state,
0531 const struct intel_plane_state *plane_state,
0532 unsigned int *num, unsigned int *den)
0533 {
0534 u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
0535 const struct drm_framebuffer *fb = plane_state->hw.fb;
0536 unsigned int cpp = fb->format->cpp[0];
0537
0538 if (hweight8(active_planes) == 2) {
0539 switch (cpp) {
0540 case 8:
0541 *num = 10;
0542 *den = 8;
0543 break;
0544 case 4:
0545 *num = 17;
0546 *den = 16;
0547 break;
0548 default:
0549 *num = 1;
0550 *den = 1;
0551 break;
0552 }
0553 } else {
0554 switch (cpp) {
0555 case 8:
0556 *num = 9;
0557 *den = 8;
0558 break;
0559 default:
0560 *num = 1;
0561 *den = 1;
0562 break;
0563 }
0564 }
0565 }
0566
0567 static void ivb_plane_ratio_scaling(const struct intel_crtc_state *crtc_state,
0568 const struct intel_plane_state *plane_state,
0569 unsigned int *num, unsigned int *den)
0570 {
0571 const struct drm_framebuffer *fb = plane_state->hw.fb;
0572 unsigned int cpp = fb->format->cpp[0];
0573
0574 switch (cpp) {
0575 case 8:
0576 *num = 12;
0577 *den = 8;
0578 break;
0579 case 4:
0580 *num = 19;
0581 *den = 16;
0582 break;
0583 case 2:
0584 *num = 33;
0585 *den = 32;
0586 break;
0587 default:
0588 *num = 1;
0589 *den = 1;
0590 break;
0591 }
0592 }
0593
0594 int ivb_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
0595 const struct intel_plane_state *plane_state)
0596 {
0597 unsigned int pixel_rate;
0598 unsigned int num, den;
0599
0600
0601
0602
0603
0604
0605
0606
0607 pixel_rate = crtc_state->pixel_rate;
0608
0609 ivb_plane_ratio(crtc_state, plane_state, &num, &den);
0610
0611 return DIV_ROUND_UP(pixel_rate * num, den);
0612 }
0613
0614 static int ivb_sprite_min_cdclk(const struct intel_crtc_state *crtc_state,
0615 const struct intel_plane_state *plane_state)
0616 {
0617 unsigned int src_w, dst_w, pixel_rate;
0618 unsigned int num, den;
0619
0620
0621
0622
0623
0624
0625
0626
0627 pixel_rate = crtc_state->pixel_rate;
0628
0629 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
0630 dst_w = drm_rect_width(&plane_state->uapi.dst);
0631
0632 if (src_w != dst_w)
0633 ivb_plane_ratio_scaling(crtc_state, plane_state, &num, &den);
0634 else
0635 ivb_plane_ratio(crtc_state, plane_state, &num, &den);
0636
0637
0638 dst_w = min(src_w, dst_w);
0639
0640 return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, num * src_w),
0641 den * dst_w);
0642 }
0643
0644 static void hsw_plane_ratio(const struct intel_crtc_state *crtc_state,
0645 const struct intel_plane_state *plane_state,
0646 unsigned int *num, unsigned int *den)
0647 {
0648 u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
0649 const struct drm_framebuffer *fb = plane_state->hw.fb;
0650 unsigned int cpp = fb->format->cpp[0];
0651
0652 if (hweight8(active_planes) == 2) {
0653 switch (cpp) {
0654 case 8:
0655 *num = 10;
0656 *den = 8;
0657 break;
0658 default:
0659 *num = 1;
0660 *den = 1;
0661 break;
0662 }
0663 } else {
0664 switch (cpp) {
0665 case 8:
0666 *num = 9;
0667 *den = 8;
0668 break;
0669 default:
0670 *num = 1;
0671 *den = 1;
0672 break;
0673 }
0674 }
0675 }
0676
0677 int hsw_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
0678 const struct intel_plane_state *plane_state)
0679 {
0680 unsigned int pixel_rate = crtc_state->pixel_rate;
0681 unsigned int num, den;
0682
0683 hsw_plane_ratio(crtc_state, plane_state, &num, &den);
0684
0685 return DIV_ROUND_UP(pixel_rate * num, den);
0686 }
0687
0688 static u32 ivb_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
0689 {
0690 u32 sprctl = 0;
0691
0692 if (crtc_state->gamma_enable)
0693 sprctl |= SPRITE_PIPE_GAMMA_ENABLE;
0694
0695 if (crtc_state->csc_enable)
0696 sprctl |= SPRITE_PIPE_CSC_ENABLE;
0697
0698 return sprctl;
0699 }
0700
0701 static bool ivb_need_sprite_gamma(const struct intel_plane_state *plane_state)
0702 {
0703 struct drm_i915_private *dev_priv =
0704 to_i915(plane_state->uapi.plane->dev);
0705 const struct drm_framebuffer *fb = plane_state->hw.fb;
0706
0707 return fb->format->cpp[0] == 8 &&
0708 (IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv));
0709 }
0710
0711 static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
0712 const struct intel_plane_state *plane_state)
0713 {
0714 struct drm_i915_private *dev_priv =
0715 to_i915(plane_state->uapi.plane->dev);
0716 const struct drm_framebuffer *fb = plane_state->hw.fb;
0717 unsigned int rotation = plane_state->hw.rotation;
0718 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
0719 u32 sprctl;
0720
0721 sprctl = SPRITE_ENABLE;
0722
0723 if (IS_IVYBRIDGE(dev_priv))
0724 sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
0725
0726 switch (fb->format->format) {
0727 case DRM_FORMAT_XBGR8888:
0728 sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
0729 break;
0730 case DRM_FORMAT_XRGB8888:
0731 sprctl |= SPRITE_FORMAT_RGBX888;
0732 break;
0733 case DRM_FORMAT_XBGR2101010:
0734 sprctl |= SPRITE_FORMAT_RGBX101010 | SPRITE_RGB_ORDER_RGBX;
0735 break;
0736 case DRM_FORMAT_XRGB2101010:
0737 sprctl |= SPRITE_FORMAT_RGBX101010;
0738 break;
0739 case DRM_FORMAT_XBGR16161616F:
0740 sprctl |= SPRITE_FORMAT_RGBX161616 | SPRITE_RGB_ORDER_RGBX;
0741 break;
0742 case DRM_FORMAT_XRGB16161616F:
0743 sprctl |= SPRITE_FORMAT_RGBX161616;
0744 break;
0745 case DRM_FORMAT_YUYV:
0746 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
0747 break;
0748 case DRM_FORMAT_YVYU:
0749 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
0750 break;
0751 case DRM_FORMAT_UYVY:
0752 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
0753 break;
0754 case DRM_FORMAT_VYUY:
0755 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
0756 break;
0757 default:
0758 MISSING_CASE(fb->format->format);
0759 return 0;
0760 }
0761
0762 if (!ivb_need_sprite_gamma(plane_state))
0763 sprctl |= SPRITE_PLANE_GAMMA_DISABLE;
0764
0765 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
0766 sprctl |= SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709;
0767
0768 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
0769 sprctl |= SPRITE_YUV_RANGE_CORRECTION_DISABLE;
0770
0771 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
0772 sprctl |= SPRITE_TILED;
0773
0774 if (rotation & DRM_MODE_ROTATE_180)
0775 sprctl |= SPRITE_ROTATE_180;
0776
0777 if (key->flags & I915_SET_COLORKEY_DESTINATION)
0778 sprctl |= SPRITE_DEST_KEY;
0779 else if (key->flags & I915_SET_COLORKEY_SOURCE)
0780 sprctl |= SPRITE_SOURCE_KEY;
0781
0782 return sprctl;
0783 }
0784
0785 static void ivb_sprite_linear_gamma(const struct intel_plane_state *plane_state,
0786 u16 gamma[18])
0787 {
0788 int scale, i;
0789
0790
0791
0792
0793
0794
0795
0796
0797
0798 scale = 4;
0799
0800 for (i = 0; i < 16; i++)
0801 gamma[i] = min((scale * i << 10) / 16, (1 << 10) - 1);
0802
0803 gamma[i] = min((scale * i << 10) / 16, 1 << 10);
0804 i++;
0805
0806 gamma[i] = 3 << 10;
0807 i++;
0808 }
0809
0810 static void ivb_sprite_update_gamma(const struct intel_plane_state *plane_state)
0811 {
0812 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
0813 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0814 enum pipe pipe = plane->pipe;
0815 u16 gamma[18];
0816 int i;
0817
0818 if (!ivb_need_sprite_gamma(plane_state))
0819 return;
0820
0821 ivb_sprite_linear_gamma(plane_state, gamma);
0822
0823
0824 for (i = 0; i < 16; i++)
0825 intel_de_write_fw(dev_priv, SPRGAMC(pipe, i),
0826 gamma[i] << 20 | gamma[i] << 10 | gamma[i]);
0827
0828 intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 0), gamma[i]);
0829 intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 1), gamma[i]);
0830 intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 2), gamma[i]);
0831 i++;
0832
0833 intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 0), gamma[i]);
0834 intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 1), gamma[i]);
0835 intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 2), gamma[i]);
0836 i++;
0837 }
0838
0839 static void
0840 ivb_sprite_update_noarm(struct intel_plane *plane,
0841 const struct intel_crtc_state *crtc_state,
0842 const struct intel_plane_state *plane_state)
0843 {
0844 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0845 enum pipe pipe = plane->pipe;
0846 int crtc_x = plane_state->uapi.dst.x1;
0847 int crtc_y = plane_state->uapi.dst.y1;
0848 u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
0849 u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
0850 u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
0851 u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
0852 u32 sprscale = 0;
0853
0854 if (crtc_w != src_w || crtc_h != src_h)
0855 sprscale = SPRITE_SCALE_ENABLE |
0856 SPRITE_SRC_WIDTH(src_w - 1) |
0857 SPRITE_SRC_HEIGHT(src_h - 1);
0858
0859 intel_de_write_fw(dev_priv, SPRSTRIDE(pipe),
0860 plane_state->view.color_plane[0].mapping_stride);
0861 intel_de_write_fw(dev_priv, SPRPOS(pipe),
0862 SPRITE_POS_Y(crtc_y) | SPRITE_POS_X(crtc_x));
0863 intel_de_write_fw(dev_priv, SPRSIZE(pipe),
0864 SPRITE_HEIGHT(crtc_h - 1) | SPRITE_WIDTH(crtc_w - 1));
0865 if (IS_IVYBRIDGE(dev_priv))
0866 intel_de_write_fw(dev_priv, SPRSCALE(pipe), sprscale);
0867 }
0868
0869 static void
0870 ivb_sprite_update_arm(struct intel_plane *plane,
0871 const struct intel_crtc_state *crtc_state,
0872 const struct intel_plane_state *plane_state)
0873 {
0874 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0875 enum pipe pipe = plane->pipe;
0876 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
0877 u32 sprsurf_offset = plane_state->view.color_plane[0].offset;
0878 u32 x = plane_state->view.color_plane[0].x;
0879 u32 y = plane_state->view.color_plane[0].y;
0880 u32 sprctl, linear_offset;
0881
0882 sprctl = plane_state->ctl | ivb_sprite_ctl_crtc(crtc_state);
0883
0884 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
0885
0886 if (key->flags) {
0887 intel_de_write_fw(dev_priv, SPRKEYVAL(pipe), key->min_value);
0888 intel_de_write_fw(dev_priv, SPRKEYMSK(pipe),
0889 key->channel_mask);
0890 intel_de_write_fw(dev_priv, SPRKEYMAX(pipe), key->max_value);
0891 }
0892
0893
0894
0895 if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
0896 intel_de_write_fw(dev_priv, SPROFFSET(pipe),
0897 SPRITE_OFFSET_Y(y) | SPRITE_OFFSET_X(x));
0898 } else {
0899 intel_de_write_fw(dev_priv, SPRLINOFF(pipe), linear_offset);
0900 intel_de_write_fw(dev_priv, SPRTILEOFF(pipe),
0901 SPRITE_OFFSET_Y(y) | SPRITE_OFFSET_X(x));
0902 }
0903
0904
0905
0906
0907
0908
0909 intel_de_write_fw(dev_priv, SPRCTL(pipe), sprctl);
0910 intel_de_write_fw(dev_priv, SPRSURF(pipe),
0911 intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
0912
0913 ivb_sprite_update_gamma(plane_state);
0914 }
0915
0916 static void
0917 ivb_sprite_disable_arm(struct intel_plane *plane,
0918 const struct intel_crtc_state *crtc_state)
0919 {
0920 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0921 enum pipe pipe = plane->pipe;
0922
0923 intel_de_write_fw(dev_priv, SPRCTL(pipe), 0);
0924
0925 if (IS_IVYBRIDGE(dev_priv))
0926 intel_de_write_fw(dev_priv, SPRSCALE(pipe), 0);
0927 intel_de_write_fw(dev_priv, SPRSURF(pipe), 0);
0928 }
0929
0930 static bool
0931 ivb_sprite_get_hw_state(struct intel_plane *plane,
0932 enum pipe *pipe)
0933 {
0934 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0935 enum intel_display_power_domain power_domain;
0936 intel_wakeref_t wakeref;
0937 bool ret;
0938
0939 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
0940 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
0941 if (!wakeref)
0942 return false;
0943
0944 ret = intel_de_read(dev_priv, SPRCTL(plane->pipe)) & SPRITE_ENABLE;
0945
0946 *pipe = plane->pipe;
0947
0948 intel_display_power_put(dev_priv, power_domain, wakeref);
0949
0950 return ret;
0951 }
0952
0953 static int g4x_sprite_min_cdclk(const struct intel_crtc_state *crtc_state,
0954 const struct intel_plane_state *plane_state)
0955 {
0956 const struct drm_framebuffer *fb = plane_state->hw.fb;
0957 unsigned int hscale, pixel_rate;
0958 unsigned int limit, decimate;
0959
0960
0961
0962
0963
0964
0965
0966
0967 pixel_rate = crtc_state->pixel_rate;
0968
0969
0970 hscale = drm_rect_calc_hscale(&plane_state->uapi.src,
0971 &plane_state->uapi.dst,
0972 0, INT_MAX);
0973 hscale = max(hscale, 0x10000u);
0974
0975
0976 decimate = ilog2(hscale >> 16);
0977 hscale >>= decimate;
0978
0979
0980 limit = 9;
0981
0982
0983 limit -= decimate;
0984
0985
0986 if (!fb->format->is_yuv)
0987 limit--;
0988
0989
0990
0991
0992
0993
0994
0995 return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, 10 * hscale),
0996 limit << 16);
0997 }
0998
0999 static unsigned int
1000 g4x_sprite_max_stride(struct intel_plane *plane,
1001 u32 pixel_format, u64 modifier,
1002 unsigned int rotation)
1003 {
1004 const struct drm_format_info *info = drm_format_info(pixel_format);
1005 int cpp = info->cpp[0];
1006
1007
1008 if (modifier == I915_FORMAT_MOD_X_TILED)
1009 return min(4096 * cpp, 16 * 1024);
1010 else
1011 return 16 * 1024;
1012 }
1013
1014 static unsigned int
1015 hsw_sprite_max_stride(struct intel_plane *plane,
1016 u32 pixel_format, u64 modifier,
1017 unsigned int rotation)
1018 {
1019 const struct drm_format_info *info = drm_format_info(pixel_format);
1020 int cpp = info->cpp[0];
1021
1022
1023 return min(8192 * cpp, 16 * 1024);
1024 }
1025
1026 static u32 g4x_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
1027 {
1028 u32 dvscntr = 0;
1029
1030 if (crtc_state->gamma_enable)
1031 dvscntr |= DVS_PIPE_GAMMA_ENABLE;
1032
1033 if (crtc_state->csc_enable)
1034 dvscntr |= DVS_PIPE_CSC_ENABLE;
1035
1036 return dvscntr;
1037 }
1038
1039 static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
1040 const struct intel_plane_state *plane_state)
1041 {
1042 struct drm_i915_private *dev_priv =
1043 to_i915(plane_state->uapi.plane->dev);
1044 const struct drm_framebuffer *fb = plane_state->hw.fb;
1045 unsigned int rotation = plane_state->hw.rotation;
1046 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1047 u32 dvscntr;
1048
1049 dvscntr = DVS_ENABLE;
1050
1051 if (IS_SANDYBRIDGE(dev_priv))
1052 dvscntr |= DVS_TRICKLE_FEED_DISABLE;
1053
1054 switch (fb->format->format) {
1055 case DRM_FORMAT_XBGR8888:
1056 dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
1057 break;
1058 case DRM_FORMAT_XRGB8888:
1059 dvscntr |= DVS_FORMAT_RGBX888;
1060 break;
1061 case DRM_FORMAT_XBGR2101010:
1062 dvscntr |= DVS_FORMAT_RGBX101010 | DVS_RGB_ORDER_XBGR;
1063 break;
1064 case DRM_FORMAT_XRGB2101010:
1065 dvscntr |= DVS_FORMAT_RGBX101010;
1066 break;
1067 case DRM_FORMAT_XBGR16161616F:
1068 dvscntr |= DVS_FORMAT_RGBX161616 | DVS_RGB_ORDER_XBGR;
1069 break;
1070 case DRM_FORMAT_XRGB16161616F:
1071 dvscntr |= DVS_FORMAT_RGBX161616;
1072 break;
1073 case DRM_FORMAT_YUYV:
1074 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
1075 break;
1076 case DRM_FORMAT_YVYU:
1077 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
1078 break;
1079 case DRM_FORMAT_UYVY:
1080 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
1081 break;
1082 case DRM_FORMAT_VYUY:
1083 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
1084 break;
1085 default:
1086 MISSING_CASE(fb->format->format);
1087 return 0;
1088 }
1089
1090 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
1091 dvscntr |= DVS_YUV_FORMAT_BT709;
1092
1093 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1094 dvscntr |= DVS_YUV_RANGE_CORRECTION_DISABLE;
1095
1096 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1097 dvscntr |= DVS_TILED;
1098
1099 if (rotation & DRM_MODE_ROTATE_180)
1100 dvscntr |= DVS_ROTATE_180;
1101
1102 if (key->flags & I915_SET_COLORKEY_DESTINATION)
1103 dvscntr |= DVS_DEST_KEY;
1104 else if (key->flags & I915_SET_COLORKEY_SOURCE)
1105 dvscntr |= DVS_SOURCE_KEY;
1106
1107 return dvscntr;
1108 }
1109
1110 static void g4x_sprite_update_gamma(const struct intel_plane_state *plane_state)
1111 {
1112 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1113 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1114 const struct drm_framebuffer *fb = plane_state->hw.fb;
1115 enum pipe pipe = plane->pipe;
1116 u16 gamma[8];
1117 int i;
1118
1119
1120 if (!fb->format->is_yuv)
1121 return;
1122
1123 i9xx_plane_linear_gamma(gamma);
1124
1125
1126
1127 for (i = 1; i < 8 - 1; i++)
1128 intel_de_write_fw(dev_priv, DVSGAMC_G4X(pipe, i - 1),
1129 gamma[i] << 16 | gamma[i] << 8 | gamma[i]);
1130 }
1131
1132 static void ilk_sprite_linear_gamma(u16 gamma[17])
1133 {
1134 int i;
1135
1136 for (i = 0; i < 17; i++)
1137 gamma[i] = (i << 10) / 16;
1138 }
1139
1140 static void ilk_sprite_update_gamma(const struct intel_plane_state *plane_state)
1141 {
1142 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1143 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1144 const struct drm_framebuffer *fb = plane_state->hw.fb;
1145 enum pipe pipe = plane->pipe;
1146 u16 gamma[17];
1147 int i;
1148
1149
1150 if (!fb->format->is_yuv)
1151 return;
1152
1153 ilk_sprite_linear_gamma(gamma);
1154
1155
1156 for (i = 0; i < 16; i++)
1157 intel_de_write_fw(dev_priv, DVSGAMC_ILK(pipe, i),
1158 gamma[i] << 20 | gamma[i] << 10 | gamma[i]);
1159
1160 intel_de_write_fw(dev_priv, DVSGAMCMAX_ILK(pipe, 0), gamma[i]);
1161 intel_de_write_fw(dev_priv, DVSGAMCMAX_ILK(pipe, 1), gamma[i]);
1162 intel_de_write_fw(dev_priv, DVSGAMCMAX_ILK(pipe, 2), gamma[i]);
1163 i++;
1164 }
1165
1166 static void
1167 g4x_sprite_update_noarm(struct intel_plane *plane,
1168 const struct intel_crtc_state *crtc_state,
1169 const struct intel_plane_state *plane_state)
1170 {
1171 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1172 enum pipe pipe = plane->pipe;
1173 int crtc_x = plane_state->uapi.dst.x1;
1174 int crtc_y = plane_state->uapi.dst.y1;
1175 u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
1176 u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
1177 u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1178 u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1179 u32 dvsscale = 0;
1180
1181 if (crtc_w != src_w || crtc_h != src_h)
1182 dvsscale = DVS_SCALE_ENABLE |
1183 DVS_SRC_WIDTH(src_w - 1) |
1184 DVS_SRC_HEIGHT(src_h - 1);
1185
1186 intel_de_write_fw(dev_priv, DVSSTRIDE(pipe),
1187 plane_state->view.color_plane[0].mapping_stride);
1188 intel_de_write_fw(dev_priv, DVSPOS(pipe),
1189 DVS_POS_Y(crtc_y) | DVS_POS_X(crtc_x));
1190 intel_de_write_fw(dev_priv, DVSSIZE(pipe),
1191 DVS_HEIGHT(crtc_h - 1) | DVS_WIDTH(crtc_w - 1));
1192 intel_de_write_fw(dev_priv, DVSSCALE(pipe), dvsscale);
1193 }
1194
1195 static void
1196 g4x_sprite_update_arm(struct intel_plane *plane,
1197 const struct intel_crtc_state *crtc_state,
1198 const struct intel_plane_state *plane_state)
1199 {
1200 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1201 enum pipe pipe = plane->pipe;
1202 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1203 u32 dvssurf_offset = plane_state->view.color_plane[0].offset;
1204 u32 x = plane_state->view.color_plane[0].x;
1205 u32 y = plane_state->view.color_plane[0].y;
1206 u32 dvscntr, linear_offset;
1207
1208 dvscntr = plane_state->ctl | g4x_sprite_ctl_crtc(crtc_state);
1209
1210 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1211
1212 if (key->flags) {
1213 intel_de_write_fw(dev_priv, DVSKEYVAL(pipe), key->min_value);
1214 intel_de_write_fw(dev_priv, DVSKEYMSK(pipe),
1215 key->channel_mask);
1216 intel_de_write_fw(dev_priv, DVSKEYMAX(pipe), key->max_value);
1217 }
1218
1219 intel_de_write_fw(dev_priv, DVSLINOFF(pipe), linear_offset);
1220 intel_de_write_fw(dev_priv, DVSTILEOFF(pipe), (y << 16) | x);
1221
1222
1223
1224
1225
1226
1227 intel_de_write_fw(dev_priv, DVSCNTR(pipe), dvscntr);
1228 intel_de_write_fw(dev_priv, DVSSURF(pipe),
1229 intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
1230
1231 if (IS_G4X(dev_priv))
1232 g4x_sprite_update_gamma(plane_state);
1233 else
1234 ilk_sprite_update_gamma(plane_state);
1235 }
1236
1237 static void
1238 g4x_sprite_disable_arm(struct intel_plane *plane,
1239 const struct intel_crtc_state *crtc_state)
1240 {
1241 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1242 enum pipe pipe = plane->pipe;
1243
1244 intel_de_write_fw(dev_priv, DVSCNTR(pipe), 0);
1245
1246 intel_de_write_fw(dev_priv, DVSSCALE(pipe), 0);
1247 intel_de_write_fw(dev_priv, DVSSURF(pipe), 0);
1248 }
1249
1250 static bool
1251 g4x_sprite_get_hw_state(struct intel_plane *plane,
1252 enum pipe *pipe)
1253 {
1254 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1255 enum intel_display_power_domain power_domain;
1256 intel_wakeref_t wakeref;
1257 bool ret;
1258
1259 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1260 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1261 if (!wakeref)
1262 return false;
1263
1264 ret = intel_de_read(dev_priv, DVSCNTR(plane->pipe)) & DVS_ENABLE;
1265
1266 *pipe = plane->pipe;
1267
1268 intel_display_power_put(dev_priv, power_domain, wakeref);
1269
1270 return ret;
1271 }
1272
1273 static bool g4x_fb_scalable(const struct drm_framebuffer *fb)
1274 {
1275 if (!fb)
1276 return false;
1277
1278 switch (fb->format->format) {
1279 case DRM_FORMAT_C8:
1280 case DRM_FORMAT_XRGB16161616F:
1281 case DRM_FORMAT_ARGB16161616F:
1282 case DRM_FORMAT_XBGR16161616F:
1283 case DRM_FORMAT_ABGR16161616F:
1284 return false;
1285 default:
1286 return true;
1287 }
1288 }
1289
1290 static int
1291 g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state,
1292 struct intel_plane_state *plane_state)
1293 {
1294 struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
1295 const struct drm_framebuffer *fb = plane_state->hw.fb;
1296 const struct drm_rect *src = &plane_state->uapi.src;
1297 const struct drm_rect *dst = &plane_state->uapi.dst;
1298 int src_x, src_w, src_h, crtc_w, crtc_h;
1299 const struct drm_display_mode *adjusted_mode =
1300 &crtc_state->hw.adjusted_mode;
1301 unsigned int stride = plane_state->view.color_plane[0].mapping_stride;
1302 unsigned int cpp = fb->format->cpp[0];
1303 unsigned int width_bytes;
1304 int min_width, min_height;
1305
1306 crtc_w = drm_rect_width(dst);
1307 crtc_h = drm_rect_height(dst);
1308
1309 src_x = src->x1 >> 16;
1310 src_w = drm_rect_width(src) >> 16;
1311 src_h = drm_rect_height(src) >> 16;
1312
1313 if (src_w == crtc_w && src_h == crtc_h)
1314 return 0;
1315
1316 min_width = 3;
1317
1318 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
1319 if (src_h & 1) {
1320 drm_dbg_kms(&i915->drm, "Source height must be even with interlaced modes\n");
1321 return -EINVAL;
1322 }
1323 min_height = 6;
1324 } else {
1325 min_height = 3;
1326 }
1327
1328 width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
1329
1330 if (src_w < min_width || src_h < min_height ||
1331 src_w > 2048 || src_h > 2048) {
1332 drm_dbg_kms(&i915->drm, "Source dimensions (%dx%d) exceed hardware limits (%dx%d - %dx%d)\n",
1333 src_w, src_h, min_width, min_height, 2048, 2048);
1334 return -EINVAL;
1335 }
1336
1337 if (width_bytes > 4096) {
1338 drm_dbg_kms(&i915->drm, "Fetch width (%d) exceeds hardware max with scaling (%u)\n",
1339 width_bytes, 4096);
1340 return -EINVAL;
1341 }
1342
1343 if (stride > 4096) {
1344 drm_dbg_kms(&i915->drm, "Stride (%u) exceeds hardware max with scaling (%u)\n",
1345 stride, 4096);
1346 return -EINVAL;
1347 }
1348
1349 return 0;
1350 }
1351
1352 static int
1353 g4x_sprite_check(struct intel_crtc_state *crtc_state,
1354 struct intel_plane_state *plane_state)
1355 {
1356 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1357 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1358 int min_scale = DRM_PLANE_HELPER_NO_SCALING;
1359 int max_scale = DRM_PLANE_HELPER_NO_SCALING;
1360 int ret;
1361
1362 if (g4x_fb_scalable(plane_state->hw.fb)) {
1363 if (DISPLAY_VER(dev_priv) < 7) {
1364 min_scale = 1;
1365 max_scale = 16 << 16;
1366 } else if (IS_IVYBRIDGE(dev_priv)) {
1367 min_scale = 1;
1368 max_scale = 2 << 16;
1369 }
1370 }
1371
1372 ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
1373 min_scale, max_scale, true);
1374 if (ret)
1375 return ret;
1376
1377 ret = i9xx_check_plane_surface(plane_state);
1378 if (ret)
1379 return ret;
1380
1381 if (!plane_state->uapi.visible)
1382 return 0;
1383
1384 ret = intel_plane_check_src_coordinates(plane_state);
1385 if (ret)
1386 return ret;
1387
1388 ret = g4x_sprite_check_scaling(crtc_state, plane_state);
1389 if (ret)
1390 return ret;
1391
1392 if (DISPLAY_VER(dev_priv) >= 7)
1393 plane_state->ctl = ivb_sprite_ctl(crtc_state, plane_state);
1394 else
1395 plane_state->ctl = g4x_sprite_ctl(crtc_state, plane_state);
1396
1397 return 0;
1398 }
1399
1400 int chv_plane_check_rotation(const struct intel_plane_state *plane_state)
1401 {
1402 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1403 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1404 unsigned int rotation = plane_state->hw.rotation;
1405
1406
1407 if (IS_CHERRYVIEW(dev_priv) &&
1408 rotation & DRM_MODE_ROTATE_180 &&
1409 rotation & DRM_MODE_REFLECT_X) {
1410 drm_dbg_kms(&dev_priv->drm,
1411 "Cannot rotate and reflect at the same time\n");
1412 return -EINVAL;
1413 }
1414
1415 return 0;
1416 }
1417
1418 static int
1419 vlv_sprite_check(struct intel_crtc_state *crtc_state,
1420 struct intel_plane_state *plane_state)
1421 {
1422 int ret;
1423
1424 ret = chv_plane_check_rotation(plane_state);
1425 if (ret)
1426 return ret;
1427
1428 ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
1429 DRM_PLANE_HELPER_NO_SCALING,
1430 DRM_PLANE_HELPER_NO_SCALING,
1431 true);
1432 if (ret)
1433 return ret;
1434
1435 ret = i9xx_check_plane_surface(plane_state);
1436 if (ret)
1437 return ret;
1438
1439 if (!plane_state->uapi.visible)
1440 return 0;
1441
1442 ret = intel_plane_check_src_coordinates(plane_state);
1443 if (ret)
1444 return ret;
1445
1446 plane_state->ctl = vlv_sprite_ctl(crtc_state, plane_state);
1447
1448 return 0;
1449 }
1450
1451 static bool has_dst_key_in_primary_plane(struct drm_i915_private *dev_priv)
1452 {
1453 return DISPLAY_VER(dev_priv) >= 9;
1454 }
1455
1456 static void intel_plane_set_ckey(struct intel_plane_state *plane_state,
1457 const struct drm_intel_sprite_colorkey *set)
1458 {
1459 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1460 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1461 struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1462
1463 *key = *set;
1464
1465
1466
1467
1468
1469 if (plane->id == PLANE_PRIMARY &&
1470 set->flags & I915_SET_COLORKEY_SOURCE)
1471 key->flags = 0;
1472
1473
1474
1475
1476
1477 if (DISPLAY_VER(dev_priv) >= 9 && plane->id != PLANE_PRIMARY &&
1478 set->flags & I915_SET_COLORKEY_DESTINATION)
1479 key->flags = 0;
1480 }
1481
1482 int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
1483 struct drm_file *file_priv)
1484 {
1485 struct drm_i915_private *dev_priv = to_i915(dev);
1486 struct drm_intel_sprite_colorkey *set = data;
1487 struct drm_plane *plane;
1488 struct drm_plane_state *plane_state;
1489 struct drm_atomic_state *state;
1490 struct drm_modeset_acquire_ctx ctx;
1491 int ret = 0;
1492
1493
1494 set->flags &= ~I915_SET_COLORKEY_NONE;
1495
1496 if (set->flags & ~(I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1497 return -EINVAL;
1498
1499
1500 if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1501 return -EINVAL;
1502
1503 if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
1504 set->flags & I915_SET_COLORKEY_DESTINATION)
1505 return -EINVAL;
1506
1507 plane = drm_plane_find(dev, file_priv, set->plane_id);
1508 if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)
1509 return -ENOENT;
1510
1511
1512
1513
1514
1515
1516 if (DISPLAY_VER(dev_priv) >= 9 &&
1517 to_intel_plane(plane)->id >= PLANE_SPRITE1 &&
1518 set->flags & I915_SET_COLORKEY_DESTINATION)
1519 return -EINVAL;
1520
1521 drm_modeset_acquire_init(&ctx, 0);
1522
1523 state = drm_atomic_state_alloc(plane->dev);
1524 if (!state) {
1525 ret = -ENOMEM;
1526 goto out;
1527 }
1528 state->acquire_ctx = &ctx;
1529
1530 while (1) {
1531 plane_state = drm_atomic_get_plane_state(state, plane);
1532 ret = PTR_ERR_OR_ZERO(plane_state);
1533 if (!ret)
1534 intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
1535
1536
1537
1538
1539
1540 if (!ret && has_dst_key_in_primary_plane(dev_priv)) {
1541 struct intel_crtc *crtc =
1542 intel_crtc_for_pipe(dev_priv,
1543 to_intel_plane(plane)->pipe);
1544
1545 plane_state = drm_atomic_get_plane_state(state,
1546 crtc->base.primary);
1547 ret = PTR_ERR_OR_ZERO(plane_state);
1548 if (!ret)
1549 intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
1550 }
1551
1552 if (!ret)
1553 ret = drm_atomic_commit(state);
1554
1555 if (ret != -EDEADLK)
1556 break;
1557
1558 drm_atomic_state_clear(state);
1559 drm_modeset_backoff(&ctx);
1560 }
1561
1562 drm_atomic_state_put(state);
1563 out:
1564 drm_modeset_drop_locks(&ctx);
1565 drm_modeset_acquire_fini(&ctx);
1566 return ret;
1567 }
1568
1569 static const u32 g4x_sprite_formats[] = {
1570 DRM_FORMAT_XRGB8888,
1571 DRM_FORMAT_YUYV,
1572 DRM_FORMAT_YVYU,
1573 DRM_FORMAT_UYVY,
1574 DRM_FORMAT_VYUY,
1575 };
1576
1577 static const u32 snb_sprite_formats[] = {
1578 DRM_FORMAT_XRGB8888,
1579 DRM_FORMAT_XBGR8888,
1580 DRM_FORMAT_XRGB2101010,
1581 DRM_FORMAT_XBGR2101010,
1582 DRM_FORMAT_XRGB16161616F,
1583 DRM_FORMAT_XBGR16161616F,
1584 DRM_FORMAT_YUYV,
1585 DRM_FORMAT_YVYU,
1586 DRM_FORMAT_UYVY,
1587 DRM_FORMAT_VYUY,
1588 };
1589
1590 static const u32 vlv_sprite_formats[] = {
1591 DRM_FORMAT_C8,
1592 DRM_FORMAT_RGB565,
1593 DRM_FORMAT_XRGB8888,
1594 DRM_FORMAT_XBGR8888,
1595 DRM_FORMAT_ARGB8888,
1596 DRM_FORMAT_ABGR8888,
1597 DRM_FORMAT_XBGR2101010,
1598 DRM_FORMAT_ABGR2101010,
1599 DRM_FORMAT_YUYV,
1600 DRM_FORMAT_YVYU,
1601 DRM_FORMAT_UYVY,
1602 DRM_FORMAT_VYUY,
1603 };
1604
1605 static const u32 chv_pipe_b_sprite_formats[] = {
1606 DRM_FORMAT_C8,
1607 DRM_FORMAT_RGB565,
1608 DRM_FORMAT_XRGB8888,
1609 DRM_FORMAT_XBGR8888,
1610 DRM_FORMAT_ARGB8888,
1611 DRM_FORMAT_ABGR8888,
1612 DRM_FORMAT_XRGB2101010,
1613 DRM_FORMAT_XBGR2101010,
1614 DRM_FORMAT_ARGB2101010,
1615 DRM_FORMAT_ABGR2101010,
1616 DRM_FORMAT_YUYV,
1617 DRM_FORMAT_YVYU,
1618 DRM_FORMAT_UYVY,
1619 DRM_FORMAT_VYUY,
1620 };
1621
1622 static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane,
1623 u32 format, u64 modifier)
1624 {
1625 if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
1626 return false;
1627
1628 switch (format) {
1629 case DRM_FORMAT_XRGB8888:
1630 case DRM_FORMAT_YUYV:
1631 case DRM_FORMAT_YVYU:
1632 case DRM_FORMAT_UYVY:
1633 case DRM_FORMAT_VYUY:
1634 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1635 modifier == I915_FORMAT_MOD_X_TILED)
1636 return true;
1637 fallthrough;
1638 default:
1639 return false;
1640 }
1641 }
1642
1643 static bool snb_sprite_format_mod_supported(struct drm_plane *_plane,
1644 u32 format, u64 modifier)
1645 {
1646 if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
1647 return false;
1648
1649 switch (format) {
1650 case DRM_FORMAT_XRGB8888:
1651 case DRM_FORMAT_XBGR8888:
1652 case DRM_FORMAT_XRGB2101010:
1653 case DRM_FORMAT_XBGR2101010:
1654 case DRM_FORMAT_XRGB16161616F:
1655 case DRM_FORMAT_XBGR16161616F:
1656 case DRM_FORMAT_YUYV:
1657 case DRM_FORMAT_YVYU:
1658 case DRM_FORMAT_UYVY:
1659 case DRM_FORMAT_VYUY:
1660 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1661 modifier == I915_FORMAT_MOD_X_TILED)
1662 return true;
1663 fallthrough;
1664 default:
1665 return false;
1666 }
1667 }
1668
1669 static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane,
1670 u32 format, u64 modifier)
1671 {
1672 if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
1673 return false;
1674
1675 switch (format) {
1676 case DRM_FORMAT_C8:
1677 case DRM_FORMAT_RGB565:
1678 case DRM_FORMAT_ABGR8888:
1679 case DRM_FORMAT_ARGB8888:
1680 case DRM_FORMAT_XBGR8888:
1681 case DRM_FORMAT_XRGB8888:
1682 case DRM_FORMAT_XBGR2101010:
1683 case DRM_FORMAT_ABGR2101010:
1684 case DRM_FORMAT_XRGB2101010:
1685 case DRM_FORMAT_ARGB2101010:
1686 case DRM_FORMAT_YUYV:
1687 case DRM_FORMAT_YVYU:
1688 case DRM_FORMAT_UYVY:
1689 case DRM_FORMAT_VYUY:
1690 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1691 modifier == I915_FORMAT_MOD_X_TILED)
1692 return true;
1693 fallthrough;
1694 default:
1695 return false;
1696 }
1697 }
1698
1699 static const struct drm_plane_funcs g4x_sprite_funcs = {
1700 .update_plane = drm_atomic_helper_update_plane,
1701 .disable_plane = drm_atomic_helper_disable_plane,
1702 .destroy = intel_plane_destroy,
1703 .atomic_duplicate_state = intel_plane_duplicate_state,
1704 .atomic_destroy_state = intel_plane_destroy_state,
1705 .format_mod_supported = g4x_sprite_format_mod_supported,
1706 };
1707
1708 static const struct drm_plane_funcs snb_sprite_funcs = {
1709 .update_plane = drm_atomic_helper_update_plane,
1710 .disable_plane = drm_atomic_helper_disable_plane,
1711 .destroy = intel_plane_destroy,
1712 .atomic_duplicate_state = intel_plane_duplicate_state,
1713 .atomic_destroy_state = intel_plane_destroy_state,
1714 .format_mod_supported = snb_sprite_format_mod_supported,
1715 };
1716
1717 static const struct drm_plane_funcs vlv_sprite_funcs = {
1718 .update_plane = drm_atomic_helper_update_plane,
1719 .disable_plane = drm_atomic_helper_disable_plane,
1720 .destroy = intel_plane_destroy,
1721 .atomic_duplicate_state = intel_plane_duplicate_state,
1722 .atomic_destroy_state = intel_plane_destroy_state,
1723 .format_mod_supported = vlv_sprite_format_mod_supported,
1724 };
1725
1726 struct intel_plane *
1727 intel_sprite_plane_create(struct drm_i915_private *dev_priv,
1728 enum pipe pipe, int sprite)
1729 {
1730 struct intel_plane *plane;
1731 const struct drm_plane_funcs *plane_funcs;
1732 unsigned int supported_rotations;
1733 const u64 *modifiers;
1734 const u32 *formats;
1735 int num_formats;
1736 int ret, zpos;
1737
1738 plane = intel_plane_alloc();
1739 if (IS_ERR(plane))
1740 return plane;
1741
1742 if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
1743 plane->update_noarm = vlv_sprite_update_noarm;
1744 plane->update_arm = vlv_sprite_update_arm;
1745 plane->disable_arm = vlv_sprite_disable_arm;
1746 plane->get_hw_state = vlv_sprite_get_hw_state;
1747 plane->check_plane = vlv_sprite_check;
1748 plane->max_stride = i965_plane_max_stride;
1749 plane->min_cdclk = vlv_plane_min_cdclk;
1750
1751 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
1752 formats = chv_pipe_b_sprite_formats;
1753 num_formats = ARRAY_SIZE(chv_pipe_b_sprite_formats);
1754 } else {
1755 formats = vlv_sprite_formats;
1756 num_formats = ARRAY_SIZE(vlv_sprite_formats);
1757 }
1758
1759 plane_funcs = &vlv_sprite_funcs;
1760 } else if (DISPLAY_VER(dev_priv) >= 7) {
1761 plane->update_noarm = ivb_sprite_update_noarm;
1762 plane->update_arm = ivb_sprite_update_arm;
1763 plane->disable_arm = ivb_sprite_disable_arm;
1764 plane->get_hw_state = ivb_sprite_get_hw_state;
1765 plane->check_plane = g4x_sprite_check;
1766
1767 if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) {
1768 plane->max_stride = hsw_sprite_max_stride;
1769 plane->min_cdclk = hsw_plane_min_cdclk;
1770 } else {
1771 plane->max_stride = g4x_sprite_max_stride;
1772 plane->min_cdclk = ivb_sprite_min_cdclk;
1773 }
1774
1775 formats = snb_sprite_formats;
1776 num_formats = ARRAY_SIZE(snb_sprite_formats);
1777
1778 plane_funcs = &snb_sprite_funcs;
1779 } else {
1780 plane->update_noarm = g4x_sprite_update_noarm;
1781 plane->update_arm = g4x_sprite_update_arm;
1782 plane->disable_arm = g4x_sprite_disable_arm;
1783 plane->get_hw_state = g4x_sprite_get_hw_state;
1784 plane->check_plane = g4x_sprite_check;
1785 plane->max_stride = g4x_sprite_max_stride;
1786 plane->min_cdclk = g4x_sprite_min_cdclk;
1787
1788 if (IS_SANDYBRIDGE(dev_priv)) {
1789 formats = snb_sprite_formats;
1790 num_formats = ARRAY_SIZE(snb_sprite_formats);
1791
1792 plane_funcs = &snb_sprite_funcs;
1793 } else {
1794 formats = g4x_sprite_formats;
1795 num_formats = ARRAY_SIZE(g4x_sprite_formats);
1796
1797 plane_funcs = &g4x_sprite_funcs;
1798 }
1799 }
1800
1801 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
1802 supported_rotations =
1803 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
1804 DRM_MODE_REFLECT_X;
1805 } else {
1806 supported_rotations =
1807 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
1808 }
1809
1810 plane->pipe = pipe;
1811 plane->id = PLANE_SPRITE0 + sprite;
1812 plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
1813
1814 modifiers = intel_fb_plane_get_modifiers(dev_priv, INTEL_PLANE_CAP_TILING_X);
1815
1816 ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
1817 0, plane_funcs,
1818 formats, num_formats, modifiers,
1819 DRM_PLANE_TYPE_OVERLAY,
1820 "sprite %c", sprite_name(pipe, sprite));
1821 kfree(modifiers);
1822
1823 if (ret)
1824 goto fail;
1825
1826 drm_plane_create_rotation_property(&plane->base,
1827 DRM_MODE_ROTATE_0,
1828 supported_rotations);
1829
1830 drm_plane_create_color_properties(&plane->base,
1831 BIT(DRM_COLOR_YCBCR_BT601) |
1832 BIT(DRM_COLOR_YCBCR_BT709),
1833 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
1834 BIT(DRM_COLOR_YCBCR_FULL_RANGE),
1835 DRM_COLOR_YCBCR_BT709,
1836 DRM_COLOR_YCBCR_LIMITED_RANGE);
1837
1838 zpos = sprite + 1;
1839 drm_plane_create_zpos_immutable_property(&plane->base, zpos);
1840
1841 intel_plane_helper_add(plane);
1842
1843 return plane;
1844
1845 fail:
1846 intel_plane_free(plane);
1847
1848 return ERR_PTR(ret);
1849 }