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; |
