diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_sprite.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_sprite.c | 494 |
1 files changed, 355 insertions, 139 deletions
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 9600ccfc5b76..d4c8e10fc90b 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c | |||
@@ -230,6 +230,56 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state) | |||
230 | #endif | 230 | #endif |
231 | } | 231 | } |
232 | 232 | ||
233 | int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state) | ||
234 | { | ||
235 | const struct drm_framebuffer *fb = plane_state->base.fb; | ||
236 | struct drm_rect *src = &plane_state->base.src; | ||
237 | u32 src_x, src_y, src_w, src_h; | ||
238 | |||
239 | /* | ||
240 | * Hardware doesn't handle subpixel coordinates. | ||
241 | * Adjust to (macro)pixel boundary, but be careful not to | ||
242 | * increase the source viewport size, because that could | ||
243 | * push the downscaling factor out of bounds. | ||
244 | */ | ||
245 | src_x = src->x1 >> 16; | ||
246 | src_w = drm_rect_width(src) >> 16; | ||
247 | src_y = src->y1 >> 16; | ||
248 | src_h = drm_rect_height(src) >> 16; | ||
249 | |||
250 | src->x1 = src_x << 16; | ||
251 | src->x2 = (src_x + src_w) << 16; | ||
252 | src->y1 = src_y << 16; | ||
253 | src->y2 = (src_y + src_h) << 16; | ||
254 | |||
255 | if (fb->format->is_yuv && | ||
256 | fb->format->format != DRM_FORMAT_NV12 && | ||
257 | (src_x & 1 || src_w & 1)) { | ||
258 | DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of 2 for YUV planes\n", | ||
259 | src_x, src_w); | ||
260 | return -EINVAL; | ||
261 | } | ||
262 | |||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | unsigned int | ||
267 | skl_plane_max_stride(struct intel_plane *plane, | ||
268 | u32 pixel_format, u64 modifier, | ||
269 | unsigned int rotation) | ||
270 | { | ||
271 | int cpp = drm_format_plane_cpp(pixel_format, 0); | ||
272 | |||
273 | /* | ||
274 | * "The stride in bytes must not exceed the | ||
275 | * of the size of 8K pixels and 32K bytes." | ||
276 | */ | ||
277 | if (drm_rotation_90_or_270(rotation)) | ||
278 | return min(8192, 32768 / cpp); | ||
279 | else | ||
280 | return min(8192 * cpp, 32768); | ||
281 | } | ||
282 | |||
233 | void | 283 | void |
234 | skl_update_plane(struct intel_plane *plane, | 284 | skl_update_plane(struct intel_plane *plane, |
235 | const struct intel_crtc_state *crtc_state, | 285 | const struct intel_crtc_state *crtc_state, |
@@ -241,16 +291,15 @@ skl_update_plane(struct intel_plane *plane, | |||
241 | enum pipe pipe = plane->pipe; | 291 | enum pipe pipe = plane->pipe; |
242 | u32 plane_ctl = plane_state->ctl; | 292 | u32 plane_ctl = plane_state->ctl; |
243 | const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; | 293 | const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; |
244 | u32 surf_addr = plane_state->main.offset; | 294 | u32 surf_addr = plane_state->color_plane[0].offset; |
245 | unsigned int rotation = plane_state->base.rotation; | 295 | u32 stride = skl_plane_stride(plane_state, 0); |
246 | u32 stride = skl_plane_stride(fb, 0, rotation); | 296 | u32 aux_stride = skl_plane_stride(plane_state, 1); |
247 | u32 aux_stride = skl_plane_stride(fb, 1, rotation); | ||
248 | int crtc_x = plane_state->base.dst.x1; | 297 | int crtc_x = plane_state->base.dst.x1; |
249 | int crtc_y = plane_state->base.dst.y1; | 298 | int crtc_y = plane_state->base.dst.y1; |
250 | uint32_t crtc_w = drm_rect_width(&plane_state->base.dst); | 299 | uint32_t crtc_w = drm_rect_width(&plane_state->base.dst); |
251 | uint32_t crtc_h = drm_rect_height(&plane_state->base.dst); | 300 | uint32_t crtc_h = drm_rect_height(&plane_state->base.dst); |
252 | uint32_t x = plane_state->main.x; | 301 | uint32_t x = plane_state->color_plane[0].x; |
253 | uint32_t y = plane_state->main.y; | 302 | uint32_t y = plane_state->color_plane[0].y; |
254 | uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16; | 303 | uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16; |
255 | uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16; | 304 | uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16; |
256 | unsigned long irqflags; | 305 | unsigned long irqflags; |
@@ -277,9 +326,10 @@ skl_update_plane(struct intel_plane *plane, | |||
277 | I915_WRITE_FW(PLANE_STRIDE(pipe, plane_id), stride); | 326 | I915_WRITE_FW(PLANE_STRIDE(pipe, plane_id), stride); |
278 | I915_WRITE_FW(PLANE_SIZE(pipe, plane_id), (src_h << 16) | src_w); | 327 | I915_WRITE_FW(PLANE_SIZE(pipe, plane_id), (src_h << 16) | src_w); |
279 | I915_WRITE_FW(PLANE_AUX_DIST(pipe, plane_id), | 328 | I915_WRITE_FW(PLANE_AUX_DIST(pipe, plane_id), |
280 | (plane_state->aux.offset - surf_addr) | aux_stride); | 329 | (plane_state->color_plane[1].offset - surf_addr) | aux_stride); |
281 | I915_WRITE_FW(PLANE_AUX_OFFSET(pipe, plane_id), | 330 | I915_WRITE_FW(PLANE_AUX_OFFSET(pipe, plane_id), |
282 | (plane_state->aux.y << 16) | plane_state->aux.x); | 331 | (plane_state->color_plane[1].y << 16) | |
332 | plane_state->color_plane[1].x); | ||
283 | 333 | ||
284 | /* program plane scaler */ | 334 | /* program plane scaler */ |
285 | if (plane_state->scaler_id >= 0) { | 335 | if (plane_state->scaler_id >= 0) { |
@@ -545,15 +595,15 @@ vlv_update_plane(struct intel_plane *plane, | |||
545 | enum pipe pipe = plane->pipe; | 595 | enum pipe pipe = plane->pipe; |
546 | enum plane_id plane_id = plane->id; | 596 | enum plane_id plane_id = plane->id; |
547 | u32 sprctl = plane_state->ctl; | 597 | u32 sprctl = plane_state->ctl; |
548 | u32 sprsurf_offset = plane_state->main.offset; | 598 | u32 sprsurf_offset = plane_state->color_plane[0].offset; |
549 | u32 linear_offset; | 599 | u32 linear_offset; |
550 | const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; | 600 | const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; |
551 | int crtc_x = plane_state->base.dst.x1; | 601 | int crtc_x = plane_state->base.dst.x1; |
552 | int crtc_y = plane_state->base.dst.y1; | 602 | int crtc_y = plane_state->base.dst.y1; |
553 | uint32_t crtc_w = drm_rect_width(&plane_state->base.dst); | 603 | uint32_t crtc_w = drm_rect_width(&plane_state->base.dst); |
554 | uint32_t crtc_h = drm_rect_height(&plane_state->base.dst); | 604 | uint32_t crtc_h = drm_rect_height(&plane_state->base.dst); |
555 | uint32_t x = plane_state->main.x; | 605 | uint32_t x = plane_state->color_plane[0].x; |
556 | uint32_t y = plane_state->main.y; | 606 | uint32_t y = plane_state->color_plane[0].y; |
557 | unsigned long irqflags; | 607 | unsigned long irqflags; |
558 | 608 | ||
559 | /* Sizes are 0 based */ | 609 | /* Sizes are 0 based */ |
@@ -574,7 +624,8 @@ vlv_update_plane(struct intel_plane *plane, | |||
574 | I915_WRITE_FW(SPKEYMAXVAL(pipe, plane_id), key->max_value); | 624 | I915_WRITE_FW(SPKEYMAXVAL(pipe, plane_id), key->max_value); |
575 | I915_WRITE_FW(SPKEYMSK(pipe, plane_id), key->channel_mask); | 625 | I915_WRITE_FW(SPKEYMSK(pipe, plane_id), key->channel_mask); |
576 | } | 626 | } |
577 | I915_WRITE_FW(SPSTRIDE(pipe, plane_id), fb->pitches[0]); | 627 | I915_WRITE_FW(SPSTRIDE(pipe, plane_id), |
628 | plane_state->color_plane[0].stride); | ||
578 | I915_WRITE_FW(SPPOS(pipe, plane_id), (crtc_y << 16) | crtc_x); | 629 | I915_WRITE_FW(SPPOS(pipe, plane_id), (crtc_y << 16) | crtc_x); |
579 | 630 | ||
580 | if (fb->modifier == I915_FORMAT_MOD_X_TILED) | 631 | if (fb->modifier == I915_FORMAT_MOD_X_TILED) |
@@ -704,15 +755,15 @@ ivb_update_plane(struct intel_plane *plane, | |||
704 | const struct drm_framebuffer *fb = plane_state->base.fb; | 755 | const struct drm_framebuffer *fb = plane_state->base.fb; |
705 | enum pipe pipe = plane->pipe; | 756 | enum pipe pipe = plane->pipe; |
706 | u32 sprctl = plane_state->ctl, sprscale = 0; | 757 | u32 sprctl = plane_state->ctl, sprscale = 0; |
707 | u32 sprsurf_offset = plane_state->main.offset; | 758 | u32 sprsurf_offset = plane_state->color_plane[0].offset; |
708 | u32 linear_offset; | 759 | u32 linear_offset; |
709 | const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; | 760 | const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; |
710 | int crtc_x = plane_state->base.dst.x1; | 761 | int crtc_x = plane_state->base.dst.x1; |
711 | int crtc_y = plane_state->base.dst.y1; | 762 | int crtc_y = plane_state->base.dst.y1; |
712 | uint32_t crtc_w = drm_rect_width(&plane_state->base.dst); | 763 | uint32_t crtc_w = drm_rect_width(&plane_state->base.dst); |
713 | uint32_t crtc_h = drm_rect_height(&plane_state->base.dst); | 764 | uint32_t crtc_h = drm_rect_height(&plane_state->base.dst); |
714 | uint32_t x = plane_state->main.x; | 765 | uint32_t x = plane_state->color_plane[0].x; |
715 | uint32_t y = plane_state->main.y; | 766 | uint32_t y = plane_state->color_plane[0].y; |
716 | uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16; | 767 | uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16; |
717 | uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16; | 768 | uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16; |
718 | unsigned long irqflags; | 769 | unsigned long irqflags; |
@@ -736,7 +787,7 @@ ivb_update_plane(struct intel_plane *plane, | |||
736 | I915_WRITE_FW(SPRKEYMSK(pipe), key->channel_mask); | 787 | I915_WRITE_FW(SPRKEYMSK(pipe), key->channel_mask); |
737 | } | 788 | } |
738 | 789 | ||
739 | I915_WRITE_FW(SPRSTRIDE(pipe), fb->pitches[0]); | 790 | I915_WRITE_FW(SPRSTRIDE(pipe), plane_state->color_plane[0].stride); |
740 | I915_WRITE_FW(SPRPOS(pipe), (crtc_y << 16) | crtc_x); | 791 | I915_WRITE_FW(SPRPOS(pipe), (crtc_y << 16) | crtc_x); |
741 | 792 | ||
742 | /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET | 793 | /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET |
@@ -749,7 +800,7 @@ ivb_update_plane(struct intel_plane *plane, | |||
749 | I915_WRITE_FW(SPRLINOFF(pipe), linear_offset); | 800 | I915_WRITE_FW(SPRLINOFF(pipe), linear_offset); |
750 | 801 | ||
751 | I915_WRITE_FW(SPRSIZE(pipe), (crtc_h << 16) | crtc_w); | 802 | I915_WRITE_FW(SPRSIZE(pipe), (crtc_h << 16) | crtc_w); |
752 | if (plane->can_scale) | 803 | if (IS_IVYBRIDGE(dev_priv)) |
753 | I915_WRITE_FW(SPRSCALE(pipe), sprscale); | 804 | I915_WRITE_FW(SPRSCALE(pipe), sprscale); |
754 | I915_WRITE_FW(SPRCTL(pipe), sprctl); | 805 | I915_WRITE_FW(SPRCTL(pipe), sprctl); |
755 | I915_WRITE_FW(SPRSURF(pipe), | 806 | I915_WRITE_FW(SPRSURF(pipe), |
@@ -770,7 +821,7 @@ ivb_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc) | |||
770 | 821 | ||
771 | I915_WRITE_FW(SPRCTL(pipe), 0); | 822 | I915_WRITE_FW(SPRCTL(pipe), 0); |
772 | /* Can't leave the scaler enabled... */ | 823 | /* Can't leave the scaler enabled... */ |
773 | if (plane->can_scale) | 824 | if (IS_IVYBRIDGE(dev_priv)) |
774 | I915_WRITE_FW(SPRSCALE(pipe), 0); | 825 | I915_WRITE_FW(SPRSCALE(pipe), 0); |
775 | 826 | ||
776 | I915_WRITE_FW(SPRSURF(pipe), 0); | 827 | I915_WRITE_FW(SPRSURF(pipe), 0); |
@@ -800,6 +851,14 @@ ivb_plane_get_hw_state(struct intel_plane *plane, | |||
800 | return ret; | 851 | return ret; |
801 | } | 852 | } |
802 | 853 | ||
854 | static unsigned int | ||
855 | g4x_sprite_max_stride(struct intel_plane *plane, | ||
856 | u32 pixel_format, u64 modifier, | ||
857 | unsigned int rotation) | ||
858 | { | ||
859 | return 16384; | ||
860 | } | ||
861 | |||
803 | static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state, | 862 | static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state, |
804 | const struct intel_plane_state *plane_state) | 863 | const struct intel_plane_state *plane_state) |
805 | { | 864 | { |
@@ -868,15 +927,15 @@ g4x_update_plane(struct intel_plane *plane, | |||
868 | const struct drm_framebuffer *fb = plane_state->base.fb; | 927 | const struct drm_framebuffer *fb = plane_state->base.fb; |
869 | enum pipe pipe = plane->pipe; | 928 | enum pipe pipe = plane->pipe; |
870 | u32 dvscntr = plane_state->ctl, dvsscale = 0; | 929 | u32 dvscntr = plane_state->ctl, dvsscale = 0; |
871 | u32 dvssurf_offset = plane_state->main.offset; | 930 | u32 dvssurf_offset = plane_state->color_plane[0].offset; |
872 | u32 linear_offset; | 931 | u32 linear_offset; |
873 | const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; | 932 | const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; |
874 | int crtc_x = plane_state->base.dst.x1; | 933 | int crtc_x = plane_state->base.dst.x1; |
875 | int crtc_y = plane_state->base.dst.y1; | 934 | int crtc_y = plane_state->base.dst.y1; |
876 | uint32_t crtc_w = drm_rect_width(&plane_state->base.dst); | 935 | uint32_t crtc_w = drm_rect_width(&plane_state->base.dst); |
877 | uint32_t crtc_h = drm_rect_height(&plane_state->base.dst); | 936 | uint32_t crtc_h = drm_rect_height(&plane_state->base.dst); |
878 | uint32_t x = plane_state->main.x; | 937 | uint32_t x = plane_state->color_plane[0].x; |
879 | uint32_t y = plane_state->main.y; | 938 | uint32_t y = plane_state->color_plane[0].y; |
880 | uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16; | 939 | uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16; |
881 | uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16; | 940 | uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16; |
882 | unsigned long irqflags; | 941 | unsigned long irqflags; |
@@ -900,7 +959,7 @@ g4x_update_plane(struct intel_plane *plane, | |||
900 | I915_WRITE_FW(DVSKEYMSK(pipe), key->channel_mask); | 959 | I915_WRITE_FW(DVSKEYMSK(pipe), key->channel_mask); |
901 | } | 960 | } |
902 | 961 | ||
903 | I915_WRITE_FW(DVSSTRIDE(pipe), fb->pitches[0]); | 962 | I915_WRITE_FW(DVSSTRIDE(pipe), plane_state->color_plane[0].stride); |
904 | I915_WRITE_FW(DVSPOS(pipe), (crtc_y << 16) | crtc_x); | 963 | I915_WRITE_FW(DVSPOS(pipe), (crtc_y << 16) | crtc_x); |
905 | 964 | ||
906 | if (fb->modifier == I915_FORMAT_MOD_X_TILED) | 965 | if (fb->modifier == I915_FORMAT_MOD_X_TILED) |
@@ -959,144 +1018,309 @@ g4x_plane_get_hw_state(struct intel_plane *plane, | |||
959 | } | 1018 | } |
960 | 1019 | ||
961 | static int | 1020 | static int |
962 | intel_check_sprite_plane(struct intel_crtc_state *crtc_state, | 1021 | g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state, |
963 | struct intel_plane_state *state) | 1022 | struct intel_plane_state *plane_state) |
964 | { | 1023 | { |
965 | struct intel_plane *plane = to_intel_plane(state->base.plane); | 1024 | const struct drm_framebuffer *fb = plane_state->base.fb; |
966 | struct drm_i915_private *dev_priv = to_i915(plane->base.dev); | 1025 | const struct drm_rect *src = &plane_state->base.src; |
967 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); | 1026 | const struct drm_rect *dst = &plane_state->base.dst; |
968 | struct drm_framebuffer *fb = state->base.fb; | 1027 | int src_x, src_y, src_w, src_h, crtc_w, crtc_h; |
969 | int max_stride = INTEL_GEN(dev_priv) >= 9 ? 32768 : 16384; | 1028 | const struct drm_display_mode *adjusted_mode = |
970 | int max_scale, min_scale; | 1029 | &crtc_state->base.adjusted_mode; |
971 | bool can_scale; | 1030 | unsigned int cpp = fb->format->cpp[0]; |
972 | int ret; | 1031 | unsigned int width_bytes; |
973 | uint32_t pixel_format = 0; | 1032 | int min_width, min_height; |
974 | 1033 | ||
975 | if (!fb) { | 1034 | crtc_w = drm_rect_width(dst); |
976 | state->base.visible = false; | 1035 | crtc_h = drm_rect_height(dst); |
1036 | |||
1037 | src_x = src->x1 >> 16; | ||
1038 | src_y = src->y1 >> 16; | ||
1039 | src_w = drm_rect_width(src) >> 16; | ||
1040 | src_h = drm_rect_height(src) >> 16; | ||
1041 | |||
1042 | if (src_w == crtc_w && src_h == crtc_h) | ||
977 | return 0; | 1043 | return 0; |
1044 | |||
1045 | min_width = 3; | ||
1046 | |||
1047 | if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { | ||
1048 | if (src_h & 1) { | ||
1049 | DRM_DEBUG_KMS("Source height must be even with interlaced modes\n"); | ||
1050 | return -EINVAL; | ||
1051 | } | ||
1052 | min_height = 6; | ||
1053 | } else { | ||
1054 | min_height = 3; | ||
978 | } | 1055 | } |
979 | 1056 | ||
980 | /* Don't modify another pipe's plane */ | 1057 | width_bytes = ((src_x * cpp) & 63) + src_w * cpp; |
981 | if (plane->pipe != crtc->pipe) { | 1058 | |
982 | DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n"); | 1059 | if (src_w < min_width || src_h < min_height || |
1060 | src_w > 2048 || src_h > 2048) { | ||
1061 | DRM_DEBUG_KMS("Source dimensions (%dx%d) exceed hardware limits (%dx%d - %dx%d)\n", | ||
1062 | src_w, src_h, min_width, min_height, 2048, 2048); | ||
983 | return -EINVAL; | 1063 | return -EINVAL; |
984 | } | 1064 | } |
985 | 1065 | ||
986 | /* FIXME check all gen limits */ | 1066 | if (width_bytes > 4096) { |
987 | if (fb->width < 3 || fb->height < 3 || fb->pitches[0] > max_stride) { | 1067 | DRM_DEBUG_KMS("Fetch width (%d) exceeds hardware max with scaling (%u)\n", |
988 | DRM_DEBUG_KMS("Unsuitable framebuffer for plane\n"); | 1068 | width_bytes, 4096); |
989 | return -EINVAL; | 1069 | return -EINVAL; |
990 | } | 1070 | } |
991 | 1071 | ||
992 | /* setup can_scale, min_scale, max_scale */ | 1072 | if (width_bytes > 4096 || fb->pitches[0] > 4096) { |
993 | if (INTEL_GEN(dev_priv) >= 9) { | 1073 | DRM_DEBUG_KMS("Stride (%u) exceeds hardware max with scaling (%u)\n", |
994 | if (state->base.fb) | 1074 | fb->pitches[0], 4096); |
995 | pixel_format = state->base.fb->format->format; | 1075 | return -EINVAL; |
996 | /* use scaler when colorkey is not required */ | 1076 | } |
997 | if (!state->ckey.flags) { | 1077 | |
998 | can_scale = 1; | 1078 | return 0; |
999 | min_scale = 1; | 1079 | } |
1000 | max_scale = | 1080 | |
1001 | skl_max_scale(crtc, crtc_state, pixel_format); | 1081 | static int |
1002 | } else { | 1082 | g4x_sprite_check(struct intel_crtc_state *crtc_state, |
1003 | can_scale = 0; | 1083 | struct intel_plane_state *plane_state) |
1004 | min_scale = DRM_PLANE_HELPER_NO_SCALING; | 1084 | { |
1005 | max_scale = DRM_PLANE_HELPER_NO_SCALING; | 1085 | struct intel_plane *plane = to_intel_plane(plane_state->base.plane); |
1006 | } | 1086 | struct drm_i915_private *dev_priv = to_i915(plane->base.dev); |
1087 | int max_scale, min_scale; | ||
1088 | int ret; | ||
1089 | |||
1090 | if (INTEL_GEN(dev_priv) < 7) { | ||
1091 | min_scale = 1; | ||
1092 | max_scale = 16 << 16; | ||
1093 | } else if (IS_IVYBRIDGE(dev_priv)) { | ||
1094 | min_scale = 1; | ||
1095 | max_scale = 2 << 16; | ||
1007 | } else { | 1096 | } else { |
1008 | can_scale = plane->can_scale; | 1097 | min_scale = DRM_PLANE_HELPER_NO_SCALING; |
1009 | max_scale = plane->max_downscale << 16; | 1098 | max_scale = DRM_PLANE_HELPER_NO_SCALING; |
1010 | min_scale = plane->can_scale ? 1 : (1 << 16); | ||
1011 | } | 1099 | } |
1012 | 1100 | ||
1013 | ret = drm_atomic_helper_check_plane_state(&state->base, | 1101 | ret = drm_atomic_helper_check_plane_state(&plane_state->base, |
1014 | &crtc_state->base, | 1102 | &crtc_state->base, |
1015 | min_scale, max_scale, | 1103 | min_scale, max_scale, |
1016 | true, true); | 1104 | true, true); |
1017 | if (ret) | 1105 | if (ret) |
1018 | return ret; | 1106 | return ret; |
1019 | 1107 | ||
1020 | if (state->base.visible) { | 1108 | if (!plane_state->base.visible) |
1021 | struct drm_rect *src = &state->base.src; | 1109 | return 0; |
1022 | struct drm_rect *dst = &state->base.dst; | 1110 | |
1023 | unsigned int crtc_w = drm_rect_width(dst); | 1111 | ret = intel_plane_check_src_coordinates(plane_state); |
1024 | unsigned int crtc_h = drm_rect_height(dst); | 1112 | if (ret) |
1025 | uint32_t src_x, src_y, src_w, src_h; | 1113 | return ret; |
1114 | |||
1115 | ret = g4x_sprite_check_scaling(crtc_state, plane_state); | ||
1116 | if (ret) | ||
1117 | return ret; | ||
1118 | |||
1119 | ret = i9xx_check_plane_surface(plane_state); | ||
1120 | if (ret) | ||
1121 | return ret; | ||
1122 | |||
1123 | if (INTEL_GEN(dev_priv) >= 7) | ||
1124 | plane_state->ctl = ivb_sprite_ctl(crtc_state, plane_state); | ||
1125 | else | ||
1126 | plane_state->ctl = g4x_sprite_ctl(crtc_state, plane_state); | ||
1127 | |||
1128 | return 0; | ||
1129 | } | ||
1130 | |||
1131 | int chv_plane_check_rotation(const struct intel_plane_state *plane_state) | ||
1132 | { | ||
1133 | struct intel_plane *plane = to_intel_plane(plane_state->base.plane); | ||
1134 | struct drm_i915_private *dev_priv = to_i915(plane->base.dev); | ||
1135 | unsigned int rotation = plane_state->base.rotation; | ||
1136 | |||
1137 | /* CHV ignores the mirror bit when the rotate bit is set :( */ | ||
1138 | if (IS_CHERRYVIEW(dev_priv) && | ||
1139 | rotation & DRM_MODE_ROTATE_180 && | ||
1140 | rotation & DRM_MODE_REFLECT_X) { | ||
1141 | DRM_DEBUG_KMS("Cannot rotate and reflect at the same time\n"); | ||
1142 | return -EINVAL; | ||
1143 | } | ||
1144 | |||
1145 | return 0; | ||
1146 | } | ||
1147 | |||
1148 | static int | ||
1149 | vlv_sprite_check(struct intel_crtc_state *crtc_state, | ||
1150 | struct intel_plane_state *plane_state) | ||
1151 | { | ||
1152 | int ret; | ||
1153 | |||
1154 | ret = chv_plane_check_rotation(plane_state); | ||
1155 | if (ret) | ||
1156 | return ret; | ||
1157 | |||
1158 | ret = drm_atomic_helper_check_plane_state(&plane_state->base, | ||
1159 | &crtc_state->base, | ||
1160 | DRM_PLANE_HELPER_NO_SCALING, | ||
1161 | DRM_PLANE_HELPER_NO_SCALING, | ||
1162 | true, true); | ||
1163 | if (ret) | ||
1164 | return ret; | ||
1165 | |||
1166 | if (!plane_state->base.visible) | ||
1167 | return 0; | ||
1168 | |||
1169 | ret = intel_plane_check_src_coordinates(plane_state); | ||
1170 | if (ret) | ||
1171 | return ret; | ||
1172 | |||
1173 | ret = i9xx_check_plane_surface(plane_state); | ||
1174 | if (ret) | ||
1175 | return ret; | ||
1176 | |||
1177 | plane_state->ctl = vlv_sprite_ctl(crtc_state, plane_state); | ||
1178 | |||
1179 | return 0; | ||
1180 | } | ||
1181 | |||
1182 | static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state, | ||
1183 | const struct intel_plane_state *plane_state) | ||
1184 | { | ||
1185 | const struct drm_framebuffer *fb = plane_state->base.fb; | ||
1186 | unsigned int rotation = plane_state->base.rotation; | ||
1187 | struct drm_format_name_buf format_name; | ||
1188 | |||
1189 | if (!fb) | ||
1190 | return 0; | ||
1191 | |||
1192 | if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) && | ||
1193 | is_ccs_modifier(fb->modifier)) { | ||
1194 | DRM_DEBUG_KMS("RC support only with 0/180 degree rotation (%x)\n", | ||
1195 | rotation); | ||
1196 | return -EINVAL; | ||
1197 | } | ||
1198 | |||
1199 | if (rotation & DRM_MODE_REFLECT_X && | ||
1200 | fb->modifier == DRM_FORMAT_MOD_LINEAR) { | ||
1201 | DRM_DEBUG_KMS("horizontal flip is not supported with linear surface formats\n"); | ||
1202 | return -EINVAL; | ||
1203 | } | ||
1204 | |||
1205 | if (drm_rotation_90_or_270(rotation)) { | ||
1206 | if (fb->modifier != I915_FORMAT_MOD_Y_TILED && | ||
1207 | fb->modifier != I915_FORMAT_MOD_Yf_TILED) { | ||
1208 | DRM_DEBUG_KMS("Y/Yf tiling required for 90/270!\n"); | ||
1209 | return -EINVAL; | ||
1210 | } | ||
1026 | 1211 | ||
1027 | /* | 1212 | /* |
1028 | * Hardware doesn't handle subpixel coordinates. | 1213 | * 90/270 is not allowed with RGB64 16:16:16:16, |
1029 | * Adjust to (macro)pixel boundary, but be careful not to | 1214 | * RGB 16-bit 5:6:5, and Indexed 8-bit. |
1030 | * increase the source viewport size, because that could | 1215 | * TBD: Add RGB64 case once its added in supported format list. |
1031 | * push the downscaling factor out of bounds. | ||
1032 | */ | 1216 | */ |
1033 | src_x = src->x1 >> 16; | 1217 | switch (fb->format->format) { |
1034 | src_w = drm_rect_width(src) >> 16; | 1218 | case DRM_FORMAT_C8: |
1035 | src_y = src->y1 >> 16; | 1219 | case DRM_FORMAT_RGB565: |
1036 | src_h = drm_rect_height(src) >> 16; | 1220 | DRM_DEBUG_KMS("Unsupported pixel format %s for 90/270!\n", |
1037 | 1221 | drm_get_format_name(fb->format->format, | |
1038 | src->x1 = src_x << 16; | 1222 | &format_name)); |
1039 | src->x2 = (src_x + src_w) << 16; | ||
1040 | src->y1 = src_y << 16; | ||
1041 | src->y2 = (src_y + src_h) << 16; | ||
1042 | |||
1043 | if (fb->format->is_yuv && | ||
1044 | fb->format->format != DRM_FORMAT_NV12 && | ||
1045 | (src_x % 2 || src_w % 2)) { | ||
1046 | DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of 2 for YUV planes\n", | ||
1047 | src_x, src_w); | ||
1048 | return -EINVAL; | 1223 | return -EINVAL; |
1224 | default: | ||
1225 | break; | ||
1049 | } | 1226 | } |
1227 | } | ||
1050 | 1228 | ||
1051 | /* Check size restrictions when scaling */ | 1229 | /* Y-tiling is not supported in IF-ID Interlace mode */ |
1052 | if (src_w != crtc_w || src_h != crtc_h) { | 1230 | if (crtc_state->base.enable && |
1053 | unsigned int width_bytes; | 1231 | crtc_state->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE && |
1054 | int cpp = fb->format->cpp[0]; | 1232 | (fb->modifier == I915_FORMAT_MOD_Y_TILED || |
1233 | fb->modifier == I915_FORMAT_MOD_Yf_TILED || | ||
1234 | fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS || | ||
1235 | fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS)) { | ||
1236 | DRM_DEBUG_KMS("Y/Yf tiling not supported in IF-ID mode\n"); | ||
1237 | return -EINVAL; | ||
1238 | } | ||
1055 | 1239 | ||
1056 | WARN_ON(!can_scale); | 1240 | return 0; |
1241 | } | ||
1057 | 1242 | ||
1058 | width_bytes = ((src_x * cpp) & 63) + src_w * cpp; | 1243 | static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_state, |
1244 | const struct intel_plane_state *plane_state) | ||
1245 | { | ||
1246 | struct drm_i915_private *dev_priv = | ||
1247 | to_i915(plane_state->base.plane->dev); | ||
1248 | int crtc_x = plane_state->base.dst.x1; | ||
1249 | int crtc_w = drm_rect_width(&plane_state->base.dst); | ||
1250 | int pipe_src_w = crtc_state->pipe_src_w; | ||
1059 | 1251 | ||
1060 | /* FIXME interlacing min height is 6 */ | 1252 | /* |
1061 | if (INTEL_GEN(dev_priv) < 9 && ( | 1253 | * Display WA #1175: cnl,glk |
1062 | src_w < 3 || src_h < 3 || | 1254 | * Planes other than the cursor may cause FIFO underflow and display |
1063 | src_w > 2048 || src_h > 2048 || | 1255 | * corruption if starting less than 4 pixels from the right edge of |
1064 | crtc_w < 3 || crtc_h < 3 || | 1256 | * the screen. |
1065 | width_bytes > 4096 || fb->pitches[0] > 4096)) { | 1257 | * Besides the above WA fix the similar problem, where planes other |
1066 | DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n"); | 1258 | * than the cursor ending less than 4 pixels from the left edge of the |
1067 | return -EINVAL; | 1259 | * screen may cause FIFO underflow and display corruption. |
1068 | } | 1260 | */ |
1069 | } | 1261 | if ((IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) && |
1262 | (crtc_x + crtc_w < 4 || crtc_x > pipe_src_w - 4)) { | ||
1263 | DRM_DEBUG_KMS("requested plane X %s position %d invalid (valid range %d-%d)\n", | ||
1264 | crtc_x + crtc_w < 4 ? "end" : "start", | ||
1265 | crtc_x + crtc_w < 4 ? crtc_x + crtc_w : crtc_x, | ||
1266 | 4, pipe_src_w - 4); | ||
1267 | return -ERANGE; | ||
1070 | } | 1268 | } |
1071 | 1269 | ||
1072 | if (INTEL_GEN(dev_priv) >= 9) { | 1270 | return 0; |
1073 | ret = skl_check_plane_surface(crtc_state, state); | 1271 | } |
1074 | if (ret) | ||
1075 | return ret; | ||
1076 | 1272 | ||
1077 | state->ctl = skl_plane_ctl(crtc_state, state); | 1273 | int skl_plane_check(struct intel_crtc_state *crtc_state, |
1078 | } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { | 1274 | struct intel_plane_state *plane_state) |
1079 | ret = i9xx_check_plane_surface(state); | 1275 | { |
1080 | if (ret) | 1276 | struct intel_plane *plane = to_intel_plane(plane_state->base.plane); |
1081 | return ret; | 1277 | struct drm_i915_private *dev_priv = to_i915(plane->base.dev); |
1278 | int max_scale, min_scale; | ||
1279 | int ret; | ||
1082 | 1280 | ||
1083 | state->ctl = vlv_sprite_ctl(crtc_state, state); | 1281 | ret = skl_plane_check_fb(crtc_state, plane_state); |
1084 | } else if (INTEL_GEN(dev_priv) >= 7) { | 1282 | if (ret) |
1085 | ret = i9xx_check_plane_surface(state); | 1283 | return ret; |
1086 | if (ret) | ||
1087 | return ret; | ||
1088 | 1284 | ||
1089 | state->ctl = ivb_sprite_ctl(crtc_state, state); | 1285 | /* use scaler when colorkey is not required */ |
1090 | } else { | 1286 | if (!plane_state->ckey.flags) { |
1091 | ret = i9xx_check_plane_surface(state); | 1287 | const struct drm_framebuffer *fb = plane_state->base.fb; |
1092 | if (ret) | ||
1093 | return ret; | ||
1094 | 1288 | ||
1095 | state->ctl = g4x_sprite_ctl(crtc_state, state); | 1289 | min_scale = 1; |
1290 | max_scale = skl_max_scale(crtc_state, | ||
1291 | fb ? fb->format->format : 0); | ||
1292 | } else { | ||
1293 | min_scale = DRM_PLANE_HELPER_NO_SCALING; | ||
1294 | max_scale = DRM_PLANE_HELPER_NO_SCALING; | ||
1096 | } | 1295 | } |
1097 | 1296 | ||
1297 | ret = drm_atomic_helper_check_plane_state(&plane_state->base, | ||
1298 | &crtc_state->base, | ||
1299 | min_scale, max_scale, | ||
1300 | true, true); | ||
1301 | if (ret) | ||
1302 | return ret; | ||
1303 | |||
1304 | if (!plane_state->base.visible) | ||
1305 | return 0; | ||
1306 | |||
1307 | ret = skl_plane_check_dst_coordinates(crtc_state, plane_state); | ||
1308 | if (ret) | ||
1309 | return ret; | ||
1310 | |||
1311 | ret = intel_plane_check_src_coordinates(plane_state); | ||
1312 | if (ret) | ||
1313 | return ret; | ||
1314 | |||
1315 | ret = skl_check_plane_surface(plane_state); | ||
1316 | if (ret) | ||
1317 | return ret; | ||
1318 | |||
1319 | plane_state->ctl = skl_plane_ctl(crtc_state, plane_state); | ||
1320 | |||
1098 | if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) | 1321 | if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) |
1099 | state->color_ctl = glk_plane_color_ctl(crtc_state, state); | 1322 | plane_state->color_ctl = glk_plane_color_ctl(crtc_state, |
1323 | plane_state); | ||
1100 | 1324 | ||
1101 | return 0; | 1325 | return 0; |
1102 | } | 1326 | } |
@@ -1523,15 +1747,16 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, | |||
1523 | intel_plane->base.state = &state->base; | 1747 | intel_plane->base.state = &state->base; |
1524 | 1748 | ||
1525 | if (INTEL_GEN(dev_priv) >= 9) { | 1749 | if (INTEL_GEN(dev_priv) >= 9) { |
1526 | intel_plane->can_scale = true; | ||
1527 | state->scaler_id = -1; | 1750 | state->scaler_id = -1; |
1528 | 1751 | ||
1529 | intel_plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, | 1752 | intel_plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, |
1530 | PLANE_SPRITE0 + plane); | 1753 | PLANE_SPRITE0 + plane); |
1531 | 1754 | ||
1755 | intel_plane->max_stride = skl_plane_max_stride; | ||
1532 | intel_plane->update_plane = skl_update_plane; | 1756 | intel_plane->update_plane = skl_update_plane; |
1533 | intel_plane->disable_plane = skl_disable_plane; | 1757 | intel_plane->disable_plane = skl_disable_plane; |
1534 | intel_plane->get_hw_state = skl_plane_get_hw_state; | 1758 | intel_plane->get_hw_state = skl_plane_get_hw_state; |
1759 | intel_plane->check_plane = skl_plane_check; | ||
1535 | 1760 | ||
1536 | if (skl_plane_has_planar(dev_priv, pipe, | 1761 | if (skl_plane_has_planar(dev_priv, pipe, |
1537 | PLANE_SPRITE0 + plane)) { | 1762 | PLANE_SPRITE0 + plane)) { |
@@ -1549,12 +1774,11 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, | |||
1549 | 1774 | ||
1550 | plane_funcs = &skl_plane_funcs; | 1775 | plane_funcs = &skl_plane_funcs; |
1551 | } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { | 1776 | } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { |
1552 | intel_plane->can_scale = false; | 1777 | intel_plane->max_stride = i9xx_plane_max_stride; |
1553 | intel_plane->max_downscale = 1; | ||
1554 | |||
1555 | intel_plane->update_plane = vlv_update_plane; | 1778 | intel_plane->update_plane = vlv_update_plane; |
1556 | intel_plane->disable_plane = vlv_disable_plane; | 1779 | intel_plane->disable_plane = vlv_disable_plane; |
1557 | intel_plane->get_hw_state = vlv_plane_get_hw_state; | 1780 | intel_plane->get_hw_state = vlv_plane_get_hw_state; |
1781 | intel_plane->check_plane = vlv_sprite_check; | ||
1558 | 1782 | ||
1559 | plane_formats = vlv_plane_formats; | 1783 | plane_formats = vlv_plane_formats; |
1560 | num_plane_formats = ARRAY_SIZE(vlv_plane_formats); | 1784 | num_plane_formats = ARRAY_SIZE(vlv_plane_formats); |
@@ -1562,17 +1786,11 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, | |||
1562 | 1786 | ||
1563 | plane_funcs = &vlv_sprite_funcs; | 1787 | plane_funcs = &vlv_sprite_funcs; |
1564 | } else if (INTEL_GEN(dev_priv) >= 7) { | 1788 | } else if (INTEL_GEN(dev_priv) >= 7) { |
1565 | if (IS_IVYBRIDGE(dev_priv)) { | 1789 | intel_plane->max_stride = g4x_sprite_max_stride; |
1566 | intel_plane->can_scale = true; | ||
1567 | intel_plane->max_downscale = 2; | ||
1568 | } else { | ||
1569 | intel_plane->can_scale = false; | ||
1570 | intel_plane->max_downscale = 1; | ||
1571 | } | ||
1572 | |||
1573 | intel_plane->update_plane = ivb_update_plane; | 1790 | intel_plane->update_plane = ivb_update_plane; |
1574 | intel_plane->disable_plane = ivb_disable_plane; | 1791 | intel_plane->disable_plane = ivb_disable_plane; |
1575 | intel_plane->get_hw_state = ivb_plane_get_hw_state; | 1792 | intel_plane->get_hw_state = ivb_plane_get_hw_state; |
1793 | intel_plane->check_plane = g4x_sprite_check; | ||
1576 | 1794 | ||
1577 | plane_formats = snb_plane_formats; | 1795 | plane_formats = snb_plane_formats; |
1578 | num_plane_formats = ARRAY_SIZE(snb_plane_formats); | 1796 | num_plane_formats = ARRAY_SIZE(snb_plane_formats); |
@@ -1580,12 +1798,11 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, | |||
1580 | 1798 | ||
1581 | plane_funcs = &snb_sprite_funcs; | 1799 | plane_funcs = &snb_sprite_funcs; |
1582 | } else { | 1800 | } else { |
1583 | intel_plane->can_scale = true; | 1801 | intel_plane->max_stride = g4x_sprite_max_stride; |
1584 | intel_plane->max_downscale = 16; | ||
1585 | |||
1586 | intel_plane->update_plane = g4x_update_plane; | 1802 | intel_plane->update_plane = g4x_update_plane; |
1587 | intel_plane->disable_plane = g4x_disable_plane; | 1803 | intel_plane->disable_plane = g4x_disable_plane; |
1588 | intel_plane->get_hw_state = g4x_plane_get_hw_state; | 1804 | intel_plane->get_hw_state = g4x_plane_get_hw_state; |
1805 | intel_plane->check_plane = g4x_sprite_check; | ||
1589 | 1806 | ||
1590 | modifiers = i9xx_plane_format_modifiers; | 1807 | modifiers = i9xx_plane_format_modifiers; |
1591 | if (IS_GEN6(dev_priv)) { | 1808 | if (IS_GEN6(dev_priv)) { |
@@ -1618,7 +1835,6 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, | |||
1618 | intel_plane->i9xx_plane = plane; | 1835 | intel_plane->i9xx_plane = plane; |
1619 | intel_plane->id = PLANE_SPRITE0 + plane; | 1836 | intel_plane->id = PLANE_SPRITE0 + plane; |
1620 | intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, intel_plane->id); | 1837 | intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, intel_plane->id); |
1621 | intel_plane->check_plane = intel_check_sprite_plane; | ||
1622 | 1838 | ||
1623 | possible_crtcs = (1 << pipe); | 1839 | possible_crtcs = (1 << pipe); |
1624 | 1840 | ||