aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_display.c
diff options
context:
space:
mode:
authorMatt Roper <matthew.d.roper@intel.com>2014-12-24 10:59:06 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2015-01-12 17:58:19 -0500
commit32b7eeec4d1e861230b09d437e95d76c86ff4a68 (patch)
tree6a286bcb28486ac21a6a8705221711dd635691b6 /drivers/gpu/drm/i915/intel_display.c
parent2f3408c7ef471dea10b8c89932f581c9c2eaf6ef (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.c199
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
11737intel_check_primary_plane(struct drm_plane *plane, 11738intel_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
11848static 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
11869static 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
11858int 11900int
@@ -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
12123finish:
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;
12111update: 12173update:
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
12126static const struct drm_plane_funcs intel_cursor_plane_funcs = { 12181static const struct drm_plane_funcs intel_cursor_plane_funcs = {