diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_sprite.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_sprite.c | 203 |
1 files changed, 119 insertions, 84 deletions
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index ad6ec4b39005..b9fabf826f7d 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c | |||
@@ -260,14 +260,14 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | |||
260 | if (obj->tiling_mode != I915_TILING_NONE) | 260 | if (obj->tiling_mode != I915_TILING_NONE) |
261 | sprctl |= SPRITE_TILED; | 261 | sprctl |= SPRITE_TILED; |
262 | 262 | ||
263 | if (IS_HASWELL(dev)) | 263 | if (IS_HASWELL(dev) || IS_BROADWELL(dev)) |
264 | sprctl &= ~SPRITE_TRICKLE_FEED_DISABLE; | 264 | sprctl &= ~SPRITE_TRICKLE_FEED_DISABLE; |
265 | else | 265 | else |
266 | sprctl |= SPRITE_TRICKLE_FEED_DISABLE; | 266 | sprctl |= SPRITE_TRICKLE_FEED_DISABLE; |
267 | 267 | ||
268 | sprctl |= SPRITE_ENABLE; | 268 | sprctl |= SPRITE_ENABLE; |
269 | 269 | ||
270 | if (IS_HASWELL(dev)) | 270 | if (IS_HASWELL(dev) || IS_BROADWELL(dev)) |
271 | sprctl |= SPRITE_PIPE_CSC_ENABLE; | 271 | sprctl |= SPRITE_PIPE_CSC_ENABLE; |
272 | 272 | ||
273 | intel_update_sprite_watermarks(plane, crtc, src_w, pixel_size, true, | 273 | intel_update_sprite_watermarks(plane, crtc, src_w, pixel_size, true, |
@@ -288,7 +288,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | |||
288 | dev_priv->sprite_scaling_enabled |= 1 << pipe; | 288 | dev_priv->sprite_scaling_enabled |= 1 << pipe; |
289 | 289 | ||
290 | if (!scaling_was_enabled) { | 290 | if (!scaling_was_enabled) { |
291 | intel_update_watermarks(dev); | 291 | intel_update_watermarks(crtc); |
292 | intel_wait_for_vblank(dev, pipe); | 292 | intel_wait_for_vblank(dev, pipe); |
293 | } | 293 | } |
294 | sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h; | 294 | sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h; |
@@ -306,7 +306,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | |||
306 | 306 | ||
307 | /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET | 307 | /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET |
308 | * register */ | 308 | * register */ |
309 | if (IS_HASWELL(dev)) | 309 | if (IS_HASWELL(dev) || IS_BROADWELL(dev)) |
310 | I915_WRITE(SPROFFSET(pipe), (y << 16) | x); | 310 | I915_WRITE(SPROFFSET(pipe), (y << 16) | x); |
311 | else if (obj->tiling_mode != I915_TILING_NONE) | 311 | else if (obj->tiling_mode != I915_TILING_NONE) |
312 | I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x); | 312 | I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x); |
@@ -323,7 +323,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | |||
323 | 323 | ||
324 | /* potentially re-enable LP watermarks */ | 324 | /* potentially re-enable LP watermarks */ |
325 | if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled) | 325 | if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled) |
326 | intel_update_watermarks(dev); | 326 | intel_update_watermarks(crtc); |
327 | } | 327 | } |
328 | 328 | ||
329 | static void | 329 | static void |
@@ -349,7 +349,7 @@ ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc) | |||
349 | 349 | ||
350 | /* potentially re-enable LP watermarks */ | 350 | /* potentially re-enable LP watermarks */ |
351 | if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled) | 351 | if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled) |
352 | intel_update_watermarks(dev); | 352 | intel_update_watermarks(crtc); |
353 | } | 353 | } |
354 | 354 | ||
355 | static int | 355 | static int |
@@ -521,13 +521,28 @@ intel_enable_primary(struct drm_crtc *crtc) | |||
521 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 521 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
522 | int reg = DSPCNTR(intel_crtc->plane); | 522 | int reg = DSPCNTR(intel_crtc->plane); |
523 | 523 | ||
524 | if (!intel_crtc->primary_disabled) | 524 | if (intel_crtc->primary_enabled) |
525 | return; | 525 | return; |
526 | 526 | ||
527 | intel_crtc->primary_disabled = false; | 527 | intel_crtc->primary_enabled = true; |
528 | intel_update_fbc(dev); | ||
529 | 528 | ||
530 | I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE); | 529 | I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE); |
530 | intel_flush_primary_plane(dev_priv, intel_crtc->plane); | ||
531 | |||
532 | /* | ||
533 | * FIXME IPS should be fine as long as one plane is | ||
534 | * enabled, but in practice it seems to have problems | ||
535 | * when going from primary only to sprite only and vice | ||
536 | * versa. | ||
537 | */ | ||
538 | if (intel_crtc->config.ips_enabled) { | ||
539 | intel_wait_for_vblank(dev, intel_crtc->pipe); | ||
540 | hsw_enable_ips(intel_crtc); | ||
541 | } | ||
542 | |||
543 | mutex_lock(&dev->struct_mutex); | ||
544 | intel_update_fbc(dev); | ||
545 | mutex_unlock(&dev->struct_mutex); | ||
531 | } | 546 | } |
532 | 547 | ||
533 | static void | 548 | static void |
@@ -538,13 +553,26 @@ intel_disable_primary(struct drm_crtc *crtc) | |||
538 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 553 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
539 | int reg = DSPCNTR(intel_crtc->plane); | 554 | int reg = DSPCNTR(intel_crtc->plane); |
540 | 555 | ||
541 | if (intel_crtc->primary_disabled) | 556 | if (!intel_crtc->primary_enabled) |
542 | return; | 557 | return; |
543 | 558 | ||
544 | I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE); | 559 | intel_crtc->primary_enabled = false; |
545 | 560 | ||
546 | intel_crtc->primary_disabled = true; | 561 | mutex_lock(&dev->struct_mutex); |
547 | intel_update_fbc(dev); | 562 | if (dev_priv->fbc.plane == intel_crtc->plane) |
563 | intel_disable_fbc(dev); | ||
564 | mutex_unlock(&dev->struct_mutex); | ||
565 | |||
566 | /* | ||
567 | * FIXME IPS should be fine as long as one plane is | ||
568 | * enabled, but in practice it seems to have problems | ||
569 | * when going from primary only to sprite only and vice | ||
570 | * versa. | ||
571 | */ | ||
572 | hsw_disable_ips(intel_crtc); | ||
573 | |||
574 | I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE); | ||
575 | intel_flush_primary_plane(dev_priv, intel_crtc->plane); | ||
548 | } | 576 | } |
549 | 577 | ||
550 | static int | 578 | static int |
@@ -623,15 +651,12 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | |||
623 | uint32_t src_w, uint32_t src_h) | 651 | uint32_t src_w, uint32_t src_h) |
624 | { | 652 | { |
625 | struct drm_device *dev = plane->dev; | 653 | struct drm_device *dev = plane->dev; |
626 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
627 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 654 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
628 | struct intel_plane *intel_plane = to_intel_plane(plane); | 655 | struct intel_plane *intel_plane = to_intel_plane(plane); |
629 | struct intel_framebuffer *intel_fb; | 656 | struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); |
630 | struct drm_i915_gem_object *obj, *old_obj; | 657 | struct drm_i915_gem_object *obj = intel_fb->obj; |
631 | int pipe = intel_plane->pipe; | 658 | struct drm_i915_gem_object *old_obj = intel_plane->obj; |
632 | enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, | 659 | int ret; |
633 | pipe); | ||
634 | int ret = 0; | ||
635 | bool disable_primary = false; | 660 | bool disable_primary = false; |
636 | bool visible; | 661 | bool visible; |
637 | int hscale, vscale; | 662 | int hscale, vscale; |
@@ -652,29 +677,23 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | |||
652 | .y2 = crtc_y + crtc_h, | 677 | .y2 = crtc_y + crtc_h, |
653 | }; | 678 | }; |
654 | const struct drm_rect clip = { | 679 | const struct drm_rect clip = { |
655 | .x2 = crtc->mode.hdisplay, | 680 | .x2 = intel_crtc->active ? intel_crtc->config.pipe_src_w : 0, |
656 | .y2 = crtc->mode.vdisplay, | 681 | .y2 = intel_crtc->active ? intel_crtc->config.pipe_src_h : 0, |
682 | }; | ||
683 | const struct { | ||
684 | int crtc_x, crtc_y; | ||
685 | unsigned int crtc_w, crtc_h; | ||
686 | uint32_t src_x, src_y, src_w, src_h; | ||
687 | } orig = { | ||
688 | .crtc_x = crtc_x, | ||
689 | .crtc_y = crtc_y, | ||
690 | .crtc_w = crtc_w, | ||
691 | .crtc_h = crtc_h, | ||
692 | .src_x = src_x, | ||
693 | .src_y = src_y, | ||
694 | .src_w = src_w, | ||
695 | .src_h = src_h, | ||
657 | }; | 696 | }; |
658 | |||
659 | intel_fb = to_intel_framebuffer(fb); | ||
660 | obj = intel_fb->obj; | ||
661 | |||
662 | old_obj = intel_plane->obj; | ||
663 | |||
664 | intel_plane->crtc_x = crtc_x; | ||
665 | intel_plane->crtc_y = crtc_y; | ||
666 | intel_plane->crtc_w = crtc_w; | ||
667 | intel_plane->crtc_h = crtc_h; | ||
668 | intel_plane->src_x = src_x; | ||
669 | intel_plane->src_y = src_y; | ||
670 | intel_plane->src_w = src_w; | ||
671 | intel_plane->src_h = src_h; | ||
672 | |||
673 | /* Pipe must be running... */ | ||
674 | if (!(I915_READ(PIPECONF(cpu_transcoder)) & PIPECONF_ENABLE)) { | ||
675 | DRM_DEBUG_KMS("Pipe disabled\n"); | ||
676 | return -EINVAL; | ||
677 | } | ||
678 | 697 | ||
679 | /* Don't modify another pipe's plane */ | 698 | /* Don't modify another pipe's plane */ |
680 | if (intel_plane->pipe != intel_crtc->pipe) { | 699 | if (intel_plane->pipe != intel_crtc->pipe) { |
@@ -810,7 +829,7 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | |||
810 | * we can disable the primary and save power. | 829 | * we can disable the primary and save power. |
811 | */ | 830 | */ |
812 | disable_primary = drm_rect_equals(&dst, &clip); | 831 | disable_primary = drm_rect_equals(&dst, &clip); |
813 | WARN_ON(disable_primary && !visible); | 832 | WARN_ON(disable_primary && !visible && intel_crtc->active); |
814 | 833 | ||
815 | mutex_lock(&dev->struct_mutex); | 834 | mutex_lock(&dev->struct_mutex); |
816 | 835 | ||
@@ -820,27 +839,40 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | |||
820 | * the sprite planes only require 128KiB alignment and 32 PTE padding. | 839 | * the sprite planes only require 128KiB alignment and 32 PTE padding. |
821 | */ | 840 | */ |
822 | ret = intel_pin_and_fence_fb_obj(dev, obj, NULL); | 841 | ret = intel_pin_and_fence_fb_obj(dev, obj, NULL); |
823 | if (ret) | ||
824 | goto out_unlock; | ||
825 | 842 | ||
826 | intel_plane->obj = obj; | 843 | mutex_unlock(&dev->struct_mutex); |
827 | |||
828 | /* | ||
829 | * Be sure to re-enable the primary before the sprite is no longer | ||
830 | * covering it fully. | ||
831 | */ | ||
832 | if (!disable_primary) | ||
833 | intel_enable_primary(crtc); | ||
834 | 844 | ||
835 | if (visible) | 845 | if (ret) |
836 | intel_plane->update_plane(plane, crtc, fb, obj, | 846 | return ret; |
837 | crtc_x, crtc_y, crtc_w, crtc_h, | 847 | |
838 | src_x, src_y, src_w, src_h); | 848 | intel_plane->crtc_x = orig.crtc_x; |
839 | else | 849 | intel_plane->crtc_y = orig.crtc_y; |
840 | intel_plane->disable_plane(plane, crtc); | 850 | intel_plane->crtc_w = orig.crtc_w; |
851 | intel_plane->crtc_h = orig.crtc_h; | ||
852 | intel_plane->src_x = orig.src_x; | ||
853 | intel_plane->src_y = orig.src_y; | ||
854 | intel_plane->src_w = orig.src_w; | ||
855 | intel_plane->src_h = orig.src_h; | ||
856 | intel_plane->obj = obj; | ||
841 | 857 | ||
842 | if (disable_primary) | 858 | if (intel_crtc->active) { |
843 | intel_disable_primary(crtc); | 859 | /* |
860 | * Be sure to re-enable the primary before the sprite is no longer | ||
861 | * covering it fully. | ||
862 | */ | ||
863 | if (!disable_primary) | ||
864 | intel_enable_primary(crtc); | ||
865 | |||
866 | if (visible) | ||
867 | intel_plane->update_plane(plane, crtc, fb, obj, | ||
868 | crtc_x, crtc_y, crtc_w, crtc_h, | ||
869 | src_x, src_y, src_w, src_h); | ||
870 | else | ||
871 | intel_plane->disable_plane(plane, crtc); | ||
872 | |||
873 | if (disable_primary) | ||
874 | intel_disable_primary(crtc); | ||
875 | } | ||
844 | 876 | ||
845 | /* Unpin old obj after new one is active to avoid ugliness */ | 877 | /* Unpin old obj after new one is active to avoid ugliness */ |
846 | if (old_obj) { | 878 | if (old_obj) { |
@@ -850,17 +882,15 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | |||
850 | * wait for vblank to avoid ugliness, we only need to | 882 | * wait for vblank to avoid ugliness, we only need to |
851 | * do the pin & ref bookkeeping. | 883 | * do the pin & ref bookkeeping. |
852 | */ | 884 | */ |
853 | if (old_obj != obj) { | 885 | if (old_obj != obj && intel_crtc->active) |
854 | mutex_unlock(&dev->struct_mutex); | 886 | intel_wait_for_vblank(dev, intel_crtc->pipe); |
855 | intel_wait_for_vblank(dev, to_intel_crtc(crtc)->pipe); | 887 | |
856 | mutex_lock(&dev->struct_mutex); | 888 | mutex_lock(&dev->struct_mutex); |
857 | } | ||
858 | intel_unpin_fb_obj(old_obj); | 889 | intel_unpin_fb_obj(old_obj); |
890 | mutex_unlock(&dev->struct_mutex); | ||
859 | } | 891 | } |
860 | 892 | ||
861 | out_unlock: | 893 | return 0; |
862 | mutex_unlock(&dev->struct_mutex); | ||
863 | return ret; | ||
864 | } | 894 | } |
865 | 895 | ||
866 | static int | 896 | static int |
@@ -868,7 +898,7 @@ intel_disable_plane(struct drm_plane *plane) | |||
868 | { | 898 | { |
869 | struct drm_device *dev = plane->dev; | 899 | struct drm_device *dev = plane->dev; |
870 | struct intel_plane *intel_plane = to_intel_plane(plane); | 900 | struct intel_plane *intel_plane = to_intel_plane(plane); |
871 | int ret = 0; | 901 | struct intel_crtc *intel_crtc; |
872 | 902 | ||
873 | if (!plane->fb) | 903 | if (!plane->fb) |
874 | return 0; | 904 | return 0; |
@@ -876,21 +906,25 @@ intel_disable_plane(struct drm_plane *plane) | |||
876 | if (WARN_ON(!plane->crtc)) | 906 | if (WARN_ON(!plane->crtc)) |
877 | return -EINVAL; | 907 | return -EINVAL; |
878 | 908 | ||
879 | intel_enable_primary(plane->crtc); | 909 | intel_crtc = to_intel_crtc(plane->crtc); |
880 | intel_plane->disable_plane(plane, plane->crtc); | ||
881 | 910 | ||
882 | if (!intel_plane->obj) | 911 | if (intel_crtc->active) { |
883 | goto out; | 912 | intel_enable_primary(plane->crtc); |
913 | intel_plane->disable_plane(plane, plane->crtc); | ||
914 | } | ||
884 | 915 | ||
885 | intel_wait_for_vblank(dev, intel_plane->pipe); | 916 | if (intel_plane->obj) { |
917 | if (intel_crtc->active) | ||
918 | intel_wait_for_vblank(dev, intel_plane->pipe); | ||
886 | 919 | ||
887 | mutex_lock(&dev->struct_mutex); | 920 | mutex_lock(&dev->struct_mutex); |
888 | intel_unpin_fb_obj(intel_plane->obj); | 921 | intel_unpin_fb_obj(intel_plane->obj); |
889 | intel_plane->obj = NULL; | 922 | mutex_unlock(&dev->struct_mutex); |
890 | mutex_unlock(&dev->struct_mutex); | ||
891 | out: | ||
892 | 923 | ||
893 | return ret; | 924 | intel_plane->obj = NULL; |
925 | } | ||
926 | |||
927 | return 0; | ||
894 | } | 928 | } |
895 | 929 | ||
896 | static void intel_destroy_plane(struct drm_plane *plane) | 930 | static void intel_destroy_plane(struct drm_plane *plane) |
@@ -921,7 +955,7 @@ int intel_sprite_set_colorkey(struct drm_device *dev, void *data, | |||
921 | 955 | ||
922 | obj = drm_mode_object_find(dev, set->plane_id, DRM_MODE_OBJECT_PLANE); | 956 | obj = drm_mode_object_find(dev, set->plane_id, DRM_MODE_OBJECT_PLANE); |
923 | if (!obj) { | 957 | if (!obj) { |
924 | ret = -EINVAL; | 958 | ret = -ENOENT; |
925 | goto out_unlock; | 959 | goto out_unlock; |
926 | } | 960 | } |
927 | 961 | ||
@@ -950,7 +984,7 @@ int intel_sprite_get_colorkey(struct drm_device *dev, void *data, | |||
950 | 984 | ||
951 | obj = drm_mode_object_find(dev, get->plane_id, DRM_MODE_OBJECT_PLANE); | 985 | obj = drm_mode_object_find(dev, get->plane_id, DRM_MODE_OBJECT_PLANE); |
952 | if (!obj) { | 986 | if (!obj) { |
953 | ret = -EINVAL; | 987 | ret = -ENOENT; |
954 | goto out_unlock; | 988 | goto out_unlock; |
955 | } | 989 | } |
956 | 990 | ||
@@ -1034,7 +1068,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) | |||
1034 | if (INTEL_INFO(dev)->gen < 5) | 1068 | if (INTEL_INFO(dev)->gen < 5) |
1035 | return -ENODEV; | 1069 | return -ENODEV; |
1036 | 1070 | ||
1037 | intel_plane = kzalloc(sizeof(struct intel_plane), GFP_KERNEL); | 1071 | intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL); |
1038 | if (!intel_plane) | 1072 | if (!intel_plane) |
1039 | return -ENOMEM; | 1073 | return -ENOMEM; |
1040 | 1074 | ||
@@ -1058,6 +1092,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) | |||
1058 | break; | 1092 | break; |
1059 | 1093 | ||
1060 | case 7: | 1094 | case 7: |
1095 | case 8: | ||
1061 | if (IS_IVYBRIDGE(dev)) { | 1096 | if (IS_IVYBRIDGE(dev)) { |
1062 | intel_plane->can_scale = true; | 1097 | intel_plane->can_scale = true; |
1063 | intel_plane->max_downscale = 2; | 1098 | intel_plane->max_downscale = 2; |