diff options
author | Matt Roper <matthew.d.roper@intel.com> | 2014-12-24 10:59:06 -0500 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2015-01-12 17:58:19 -0500 |
commit | 32b7eeec4d1e861230b09d437e95d76c86ff4a68 (patch) | |
tree | 6a286bcb28486ac21a6a8705221711dd635691b6 /drivers/gpu/drm/i915/intel_display.c | |
parent | 2f3408c7ef471dea10b8c89932f581c9c2eaf6ef (diff) |
drm/i915: Refactor work that can sleep out of commit (v7)
Once we integrate our work into the atomic pipeline, plane commit
operations will need to happen with interrupts disabled, due to vblank
evasion. Our commit functions today include sleepable work, so those
operations need to be split out and run either before or after the
atomic register programming.
The solution here calculates which of those operations will need to be
performed during the 'check' phase and sets flags in an intel_crtc
sub-struct. New intel_begin_crtc_commit() and
intel_finish_crtc_commit() functions are added before and after the
actual register programming; these will eventually be called from the
atomic plane helper's .atomic_begin() and .atomic_end() entrypoints.
v2: Fix broken sprite code split
v3: Make the pre/post commit work crtc-based to match how we eventually
want this to be called from the atomic plane helpers.
v4: Some platforms that haven't had their watermark code reworked were
waiting for vblank, then calling update_sprite_watermarks in their
platform-specific disable code. These also need to be flagged out
of the critical section.
v5: Sprite plane test for primary show/hide should just set the flag to
wait for pending flips, not actually perform the wait. (Ander)
v6:
- Rebase onto latest di-nightly; picks up an important runtime PM fix.
- Handle 'wait_for_flips' flag in intel_begin_crtc_commit(). (Ander)
- Use wait_for_flips flag for primary plane update rather than
performing the wait in the check routine.
- Added kerneldoc to pre_disable/post_enable functions that are no
longer static. (Ander)
- Replace assert_pipe_enabled() in intel_disable_primary_hw_plane()
with an intel_crtc->active test; it turns out assert_pipe_enabled()
grabs some mutexes and can sleep, which we can't do with interrupts
disabled.
v7:
- Check for fb != NULL when deciding whether the sprite plane hides the
primary plane during a sprite update. (PRTS)
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Reviewed-by: Ander Conselvan de Oliveira <conselvan2@gmail.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 199 |
1 files changed, 127 insertions, 72 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a340f51c790a..260b91c4cbbf 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -2165,7 +2165,8 @@ static void intel_disable_primary_hw_plane(struct drm_plane *plane, | |||
2165 | struct drm_i915_private *dev_priv = dev->dev_private; | 2165 | struct drm_i915_private *dev_priv = dev->dev_private; |
2166 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 2166 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
2167 | 2167 | ||
2168 | assert_pipe_enabled(dev_priv, intel_crtc->pipe); | 2168 | if (WARN_ON(!intel_crtc->active)) |
2169 | return; | ||
2169 | 2170 | ||
2170 | if (!intel_crtc->primary_enabled) | 2171 | if (!intel_crtc->primary_enabled) |
2171 | return; | 2172 | return; |
@@ -11737,7 +11738,11 @@ static int | |||
11737 | intel_check_primary_plane(struct drm_plane *plane, | 11738 | intel_check_primary_plane(struct drm_plane *plane, |
11738 | struct intel_plane_state *state) | 11739 | struct intel_plane_state *state) |
11739 | { | 11740 | { |
11741 | struct drm_device *dev = plane->dev; | ||
11742 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
11740 | struct drm_crtc *crtc = state->base.crtc; | 11743 | struct drm_crtc *crtc = state->base.crtc; |
11744 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
11745 | struct intel_plane *intel_plane = to_intel_plane(plane); | ||
11741 | struct drm_framebuffer *fb = state->base.fb; | 11746 | struct drm_framebuffer *fb = state->base.fb; |
11742 | struct drm_rect *dest = &state->dst; | 11747 | struct drm_rect *dest = &state->dst; |
11743 | struct drm_rect *src = &state->src; | 11748 | struct drm_rect *src = &state->src; |
@@ -11752,10 +11757,40 @@ intel_check_primary_plane(struct drm_plane *plane, | |||
11752 | if (ret) | 11757 | if (ret) |
11753 | return ret; | 11758 | return ret; |
11754 | 11759 | ||
11755 | intel_crtc_wait_for_pending_flips(crtc); | 11760 | if (intel_crtc->active) { |
11756 | if (intel_crtc_has_pending_flip(crtc)) { | 11761 | intel_crtc->atomic.wait_for_flips = true; |
11757 | DRM_ERROR("pipe is still busy with an old pageflip\n"); | 11762 | |
11758 | return -EBUSY; | 11763 | /* |
11764 | * FBC does not work on some platforms for rotated | ||
11765 | * planes, so disable it when rotation is not 0 and | ||
11766 | * update it when rotation is set back to 0. | ||
11767 | * | ||
11768 | * FIXME: This is redundant with the fbc update done in | ||
11769 | * the primary plane enable function except that that | ||
11770 | * one is done too late. We eventually need to unify | ||
11771 | * this. | ||
11772 | */ | ||
11773 | if (intel_crtc->primary_enabled && | ||
11774 | INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev) && | ||
11775 | dev_priv->fbc.plane == intel_crtc->plane && | ||
11776 | intel_plane->rotation != BIT(DRM_ROTATE_0)) { | ||
11777 | intel_crtc->atomic.disable_fbc = true; | ||
11778 | } | ||
11779 | |||
11780 | if (state->visible) { | ||
11781 | /* | ||
11782 | * BDW signals flip done immediately if the plane | ||
11783 | * is disabled, even if the plane enable is already | ||
11784 | * armed to occur at the next vblank :( | ||
11785 | */ | ||
11786 | if (IS_BROADWELL(dev) && !intel_crtc->primary_enabled) | ||
11787 | intel_crtc->atomic.wait_vblank = true; | ||
11788 | } | ||
11789 | |||
11790 | intel_crtc->atomic.fb_bits |= | ||
11791 | INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe); | ||
11792 | |||
11793 | intel_crtc->atomic.update_fbc = true; | ||
11759 | } | 11794 | } |
11760 | 11795 | ||
11761 | return 0; | 11796 | return 0; |
@@ -11773,18 +11808,6 @@ intel_commit_primary_plane(struct drm_plane *plane, | |||
11773 | struct drm_i915_gem_object *obj = intel_fb_obj(fb); | 11808 | struct drm_i915_gem_object *obj = intel_fb_obj(fb); |
11774 | struct intel_plane *intel_plane = to_intel_plane(plane); | 11809 | struct intel_plane *intel_plane = to_intel_plane(plane); |
11775 | struct drm_rect *src = &state->src; | 11810 | struct drm_rect *src = &state->src; |
11776 | enum pipe pipe = intel_plane->pipe; | ||
11777 | |||
11778 | if (!fb) { | ||
11779 | /* | ||
11780 | * 'prepare' is never called when plane is being disabled, so | ||
11781 | * we need to handle frontbuffer tracking here | ||
11782 | */ | ||
11783 | mutex_lock(&dev->struct_mutex); | ||
11784 | i915_gem_track_fb(intel_fb_obj(plane->fb), NULL, | ||
11785 | INTEL_FRONTBUFFER_PRIMARY(pipe)); | ||
11786 | mutex_unlock(&dev->struct_mutex); | ||
11787 | } | ||
11788 | 11811 | ||
11789 | plane->fb = fb; | 11812 | plane->fb = fb; |
11790 | crtc->x = src->x1 >> 16; | 11813 | crtc->x = src->x1 >> 16; |
@@ -11801,26 +11824,7 @@ intel_commit_primary_plane(struct drm_plane *plane, | |||
11801 | intel_plane->obj = obj; | 11824 | intel_plane->obj = obj; |
11802 | 11825 | ||
11803 | if (intel_crtc->active) { | 11826 | if (intel_crtc->active) { |
11804 | /* | ||
11805 | * FBC does not work on some platforms for rotated | ||
11806 | * planes, so disable it when rotation is not 0 and | ||
11807 | * update it when rotation is set back to 0. | ||
11808 | * | ||
11809 | * FIXME: This is redundant with the fbc update done in | ||
11810 | * the primary plane enable function except that that | ||
11811 | * one is done too late. We eventually need to unify | ||
11812 | * this. | ||
11813 | */ | ||
11814 | if (intel_crtc->primary_enabled && | ||
11815 | INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev) && | ||
11816 | dev_priv->fbc.plane == intel_crtc->plane && | ||
11817 | intel_plane->rotation != BIT(DRM_ROTATE_0)) { | ||
11818 | intel_fbc_disable(dev); | ||
11819 | } | ||
11820 | |||
11821 | if (state->visible) { | 11827 | if (state->visible) { |
11822 | bool was_enabled = intel_crtc->primary_enabled; | ||
11823 | |||
11824 | /* FIXME: kill this fastboot hack */ | 11828 | /* FIXME: kill this fastboot hack */ |
11825 | intel_update_pipe_size(intel_crtc); | 11829 | intel_update_pipe_size(intel_crtc); |
11826 | 11830 | ||
@@ -11828,14 +11832,6 @@ intel_commit_primary_plane(struct drm_plane *plane, | |||
11828 | 11832 | ||
11829 | dev_priv->display.update_primary_plane(crtc, plane->fb, | 11833 | dev_priv->display.update_primary_plane(crtc, plane->fb, |
11830 | crtc->x, crtc->y); | 11834 | crtc->x, crtc->y); |
11831 | |||
11832 | /* | ||
11833 | * BDW signals flip done immediately if the plane | ||
11834 | * is disabled, even if the plane enable is already | ||
11835 | * armed to occur at the next vblank :( | ||
11836 | */ | ||
11837 | if (IS_BROADWELL(dev) && !was_enabled) | ||
11838 | intel_wait_for_vblank(dev, intel_crtc->pipe); | ||
11839 | } else { | 11835 | } else { |
11840 | /* | 11836 | /* |
11841 | * If clipping results in a non-visible primary plane, | 11837 | * If clipping results in a non-visible primary plane, |
@@ -11846,13 +11842,59 @@ intel_commit_primary_plane(struct drm_plane *plane, | |||
11846 | */ | 11842 | */ |
11847 | intel_disable_primary_hw_plane(plane, crtc); | 11843 | intel_disable_primary_hw_plane(plane, crtc); |
11848 | } | 11844 | } |
11845 | } | ||
11846 | } | ||
11847 | |||
11848 | static void intel_begin_crtc_commit(struct drm_crtc *crtc) | ||
11849 | { | ||
11850 | struct drm_device *dev = crtc->dev; | ||
11851 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
11852 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
11849 | 11853 | ||
11850 | intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_PRIMARY(pipe)); | 11854 | if (intel_crtc->atomic.wait_for_flips) |
11855 | intel_crtc_wait_for_pending_flips(crtc); | ||
11851 | 11856 | ||
11857 | if (intel_crtc->atomic.disable_fbc) | ||
11858 | intel_fbc_disable(dev); | ||
11859 | |||
11860 | if (intel_crtc->atomic.pre_disable_primary) | ||
11861 | intel_pre_disable_primary(crtc); | ||
11862 | |||
11863 | if (intel_crtc->atomic.update_wm) | ||
11864 | intel_update_watermarks(crtc); | ||
11865 | |||
11866 | intel_runtime_pm_get(dev_priv); | ||
11867 | } | ||
11868 | |||
11869 | static void intel_finish_crtc_commit(struct drm_crtc *crtc) | ||
11870 | { | ||
11871 | struct drm_device *dev = crtc->dev; | ||
11872 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
11873 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
11874 | struct drm_plane *p; | ||
11875 | |||
11876 | intel_runtime_pm_put(dev_priv); | ||
11877 | |||
11878 | if (intel_crtc->atomic.wait_vblank) | ||
11879 | intel_wait_for_vblank(dev, intel_crtc->pipe); | ||
11880 | |||
11881 | intel_frontbuffer_flip(dev, intel_crtc->atomic.fb_bits); | ||
11882 | |||
11883 | if (intel_crtc->atomic.update_fbc) { | ||
11852 | mutex_lock(&dev->struct_mutex); | 11884 | mutex_lock(&dev->struct_mutex); |
11853 | intel_fbc_update(dev); | 11885 | intel_fbc_update(dev); |
11854 | mutex_unlock(&dev->struct_mutex); | 11886 | mutex_unlock(&dev->struct_mutex); |
11855 | } | 11887 | } |
11888 | |||
11889 | if (intel_crtc->atomic.post_enable_primary) | ||
11890 | intel_post_enable_primary(crtc); | ||
11891 | |||
11892 | drm_for_each_legacy_plane(p, &dev->mode_config.plane_list) | ||
11893 | if (intel_crtc->atomic.update_sprite_watermarks & drm_plane_index(p)) | ||
11894 | intel_update_sprite_watermarks(p, crtc, 0, 0, 0, | ||
11895 | false, false); | ||
11896 | |||
11897 | memset(&intel_crtc->atomic, 0, sizeof(intel_crtc->atomic)); | ||
11856 | } | 11898 | } |
11857 | 11899 | ||
11858 | int | 11900 | int |
@@ -11863,9 +11905,8 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | |||
11863 | uint32_t src_w, uint32_t src_h) | 11905 | uint32_t src_w, uint32_t src_h) |
11864 | { | 11906 | { |
11865 | struct drm_device *dev = plane->dev; | 11907 | struct drm_device *dev = plane->dev; |
11866 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
11867 | struct drm_framebuffer *old_fb = plane->fb; | 11908 | struct drm_framebuffer *old_fb = plane->fb; |
11868 | struct intel_plane_state state; | 11909 | struct intel_plane_state state = {{ 0 }}; |
11869 | struct intel_plane *intel_plane = to_intel_plane(plane); | 11910 | struct intel_plane *intel_plane = to_intel_plane(plane); |
11870 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 11911 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
11871 | int ret; | 11912 | int ret; |
@@ -11903,9 +11944,33 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | |||
11903 | return ret; | 11944 | return ret; |
11904 | } | 11945 | } |
11905 | 11946 | ||
11906 | intel_runtime_pm_get(dev_priv); | 11947 | if (!state.base.fb) { |
11948 | unsigned fb_bits = 0; | ||
11949 | |||
11950 | switch (plane->type) { | ||
11951 | case DRM_PLANE_TYPE_PRIMARY: | ||
11952 | fb_bits = INTEL_FRONTBUFFER_PRIMARY(intel_plane->pipe); | ||
11953 | break; | ||
11954 | case DRM_PLANE_TYPE_CURSOR: | ||
11955 | fb_bits = INTEL_FRONTBUFFER_CURSOR(intel_plane->pipe); | ||
11956 | break; | ||
11957 | case DRM_PLANE_TYPE_OVERLAY: | ||
11958 | fb_bits = INTEL_FRONTBUFFER_SPRITE(intel_plane->pipe); | ||
11959 | break; | ||
11960 | } | ||
11961 | |||
11962 | /* | ||
11963 | * 'prepare' is never called when plane is being disabled, so | ||
11964 | * we need to handle frontbuffer tracking here | ||
11965 | */ | ||
11966 | mutex_lock(&dev->struct_mutex); | ||
11967 | i915_gem_track_fb(intel_fb_obj(plane->fb), NULL, fb_bits); | ||
11968 | mutex_unlock(&dev->struct_mutex); | ||
11969 | } | ||
11970 | |||
11971 | intel_begin_crtc_commit(crtc); | ||
11907 | intel_plane->commit_plane(plane, &state); | 11972 | intel_plane->commit_plane(plane, &state); |
11908 | intel_runtime_pm_put(dev_priv); | 11973 | intel_finish_crtc_commit(crtc); |
11909 | 11974 | ||
11910 | if (fb != old_fb && old_fb) { | 11975 | if (fb != old_fb && old_fb) { |
11911 | if (intel_crtc->active) | 11976 | if (intel_crtc->active) |
@@ -12012,6 +12077,7 @@ intel_check_cursor_plane(struct drm_plane *plane, | |||
12012 | struct drm_rect *src = &state->src; | 12077 | struct drm_rect *src = &state->src; |
12013 | const struct drm_rect *clip = &state->clip; | 12078 | const struct drm_rect *clip = &state->clip; |
12014 | struct drm_i915_gem_object *obj = intel_fb_obj(fb); | 12079 | struct drm_i915_gem_object *obj = intel_fb_obj(fb); |
12080 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
12015 | int crtc_w, crtc_h; | 12081 | int crtc_w, crtc_h; |
12016 | unsigned stride; | 12082 | unsigned stride; |
12017 | int ret; | 12083 | int ret; |
@@ -12027,7 +12093,7 @@ intel_check_cursor_plane(struct drm_plane *plane, | |||
12027 | 12093 | ||
12028 | /* if we want to turn off the cursor ignore width and height */ | 12094 | /* if we want to turn off the cursor ignore width and height */ |
12029 | if (!obj) | 12095 | if (!obj) |
12030 | return 0; | 12096 | goto finish; |
12031 | 12097 | ||
12032 | /* Check for which cursor types we support */ | 12098 | /* Check for which cursor types we support */ |
12033 | crtc_w = drm_rect_width(&state->orig_dst); | 12099 | crtc_w = drm_rect_width(&state->orig_dst); |
@@ -12054,6 +12120,16 @@ intel_check_cursor_plane(struct drm_plane *plane, | |||
12054 | } | 12120 | } |
12055 | mutex_unlock(&dev->struct_mutex); | 12121 | mutex_unlock(&dev->struct_mutex); |
12056 | 12122 | ||
12123 | finish: | ||
12124 | if (intel_crtc->active) { | ||
12125 | if (intel_crtc->cursor_width != | ||
12126 | drm_rect_width(&state->orig_dst)) | ||
12127 | intel_crtc->atomic.update_wm = true; | ||
12128 | |||
12129 | intel_crtc->atomic.fb_bits |= | ||
12130 | INTEL_FRONTBUFFER_CURSOR(intel_crtc->pipe); | ||
12131 | } | ||
12132 | |||
12057 | return ret; | 12133 | return ret; |
12058 | } | 12134 | } |
12059 | 12135 | ||
@@ -12066,9 +12142,6 @@ intel_commit_cursor_plane(struct drm_plane *plane, | |||
12066 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 12142 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
12067 | struct intel_plane *intel_plane = to_intel_plane(plane); | 12143 | struct intel_plane *intel_plane = to_intel_plane(plane); |
12068 | struct drm_i915_gem_object *obj = intel_fb_obj(state->base.fb); | 12144 | struct drm_i915_gem_object *obj = intel_fb_obj(state->base.fb); |
12069 | struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb); | ||
12070 | enum pipe pipe = intel_crtc->pipe; | ||
12071 | unsigned old_width; | ||
12072 | uint32_t addr; | 12145 | uint32_t addr; |
12073 | 12146 | ||
12074 | plane->fb = state->base.fb; | 12147 | plane->fb = state->base.fb; |
@@ -12088,17 +12161,6 @@ intel_commit_cursor_plane(struct drm_plane *plane, | |||
12088 | if (intel_crtc->cursor_bo == obj) | 12161 | if (intel_crtc->cursor_bo == obj) |
12089 | goto update; | 12162 | goto update; |
12090 | 12163 | ||
12091 | /* | ||
12092 | * 'prepare' is only called when fb != NULL; we still need to update | ||
12093 | * frontbuffer tracking for the 'disable' case here. | ||
12094 | */ | ||
12095 | if (!obj) { | ||
12096 | mutex_lock(&dev->struct_mutex); | ||
12097 | i915_gem_track_fb(old_obj, NULL, | ||
12098 | INTEL_FRONTBUFFER_CURSOR(pipe)); | ||
12099 | mutex_unlock(&dev->struct_mutex); | ||
12100 | } | ||
12101 | |||
12102 | if (!obj) | 12164 | if (!obj) |
12103 | addr = 0; | 12165 | addr = 0; |
12104 | else if (!INTEL_INFO(dev)->cursor_needs_physical) | 12166 | else if (!INTEL_INFO(dev)->cursor_needs_physical) |
@@ -12109,18 +12171,11 @@ intel_commit_cursor_plane(struct drm_plane *plane, | |||
12109 | intel_crtc->cursor_addr = addr; | 12171 | intel_crtc->cursor_addr = addr; |
12110 | intel_crtc->cursor_bo = obj; | 12172 | intel_crtc->cursor_bo = obj; |
12111 | update: | 12173 | update: |
12112 | old_width = intel_crtc->cursor_width; | ||
12113 | |||
12114 | intel_crtc->cursor_width = drm_rect_width(&state->orig_dst); | 12174 | intel_crtc->cursor_width = drm_rect_width(&state->orig_dst); |
12115 | intel_crtc->cursor_height = drm_rect_height(&state->orig_dst); | 12175 | intel_crtc->cursor_height = drm_rect_height(&state->orig_dst); |
12116 | 12176 | ||
12117 | if (intel_crtc->active) { | 12177 | if (intel_crtc->active) |
12118 | if (old_width != intel_crtc->cursor_width) | ||
12119 | intel_update_watermarks(crtc); | ||
12120 | intel_crtc_update_cursor(crtc, state->visible); | 12178 | intel_crtc_update_cursor(crtc, state->visible); |
12121 | |||
12122 | intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_CURSOR(pipe)); | ||
12123 | } | ||
12124 | } | 12179 | } |
12125 | 12180 | ||
12126 | static const struct drm_plane_funcs intel_cursor_plane_funcs = { | 12181 | static const struct drm_plane_funcs intel_cursor_plane_funcs = { |