Message ID | 1417537562-20978-1-git-send-email-matthew.d.roper@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 12/02/2014 06:26 PM, Matt Roper wrote: > If we extend the commit_plane handlers for each plane type to be able to > handle fb=0, then we can easily implement plane disable via the > update_plane handler. The cursor plane already works this way, and this > is the direction we need to go to integrate with the atomic plane > handler. We can now kill off the type-specific disable functions, as > well as the redundant intel_plane_disable() (not to be confused with > intel_disable_plane()). > > Note that prepare_plane_fb() only gets called as part of update_plane > when fb!=NULL (by design, to match the semantics of the atomic plane > helpers); this means that our commit_plane handlers need to handle the > frontbuffer tracking for the disable case, even though they don't handle > it for normal updates. > > v2: > - Change BUG_ON to WARN_ON (Ander/Daniel) > > v3: > - Drop unnecessary plane->crtc check since a previous patch to plane > update ensures that plane->crtc will always be non-NULL, even for > disable calls that might pass NULL from userspace. (Ander) > - Drop a s/crtc/plane->crtc/ hunk that was unnecessary. (Ander) > > v4: > - Fix missing whitespace (Ander) > > Signed-off-by: Matt Roper <matthew.d.roper@intel.com> > Reviewed-by: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com> > --- > drivers/gpu/drm/i915/intel_display.c | 93 ++++++++++++++---------------------- > drivers/gpu/drm/i915/intel_drv.h | 2 +- > drivers/gpu/drm/i915/intel_sprite.c | 71 +++++++-------------------- > 3 files changed, 56 insertions(+), 110 deletions(-) > > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c > index d13015c..eb422bf 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -4060,7 +4060,7 @@ static void intel_disable_planes(struct drm_crtc *crtc) > drm_for_each_legacy_plane(plane, &dev->mode_config.plane_list) { > intel_plane = to_intel_plane(plane); > if (intel_plane->pipe == pipe) > - intel_plane_disable(&intel_plane->base); > + plane->funcs->disable_plane(plane); > } > } > > @@ -11605,43 +11605,6 @@ static void intel_shared_dpll_init(struct drm_device *dev) > BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS); > } > > -static int > -intel_primary_plane_disable(struct drm_plane *plane) > -{ > - struct drm_device *dev = plane->dev; > - struct intel_crtc *intel_crtc; > - > - if (!plane->fb) > - return 0; > - > - BUG_ON(!plane->crtc); > - > - intel_crtc = to_intel_crtc(plane->crtc); > - > - /* > - * Even though we checked plane->fb above, it's still possible that > - * the primary plane has been implicitly disabled because the crtc > - * coordinates given weren't visible, or because we detected > - * that it was 100% covered by a sprite plane. Or, the CRTC may be > - * off and we've set a fb, but haven't actually turned on the CRTC yet. > - * In either case, we need to unpin the FB and let the fb pointer get > - * updated, but otherwise we don't need to touch the hardware. > - */ > - if (intel_crtc->primary_enabled) { > - intel_crtc_wait_for_pending_flips(plane->crtc); > - intel_disable_primary_hw_plane(plane, plane->crtc); > - } > - > - mutex_lock(&dev->struct_mutex); > - i915_gem_track_fb(intel_fb_obj(plane->fb), NULL, > - INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe)); > - intel_unpin_fb_obj(intel_fb_obj(plane->fb)); > - mutex_unlock(&dev->struct_mutex); > - plane->fb = NULL; > - > - return 0; > -} > - > /** > * intel_prepare_plane_fb - Prepare fb for usage on plane > * @plane: drm plane to prepare for > @@ -11745,8 +11708,8 @@ intel_check_primary_plane(struct drm_plane *plane, > if (ret) > return ret; > > - intel_crtc_wait_for_pending_flips(crtc); > - if (intel_crtc_has_pending_flip(crtc)) { > + intel_crtc_wait_for_pending_flips(plane->crtc); > + if (intel_crtc_has_pending_flip(plane->crtc)) { So it turns out plane->crtc can be NULL here, when we enable the plane for the first time. After drm_mode_set_config_internal() succeeds, it sets primary->crtc and nothing else resets it to NULL. Now, in patch 9 you made sure state->base.crtc is always valid, so we could just leave this hunk unchanged, or put back the 'if (plane->crtc)' check. Sorry for the confusion. Cheers, Ander > DRM_ERROR("pipe is still busy with an old pageflip\n"); > return -EBUSY; > } > @@ -11763,12 +11726,23 @@ intel_commit_primary_plane(struct drm_plane *plane, > struct drm_device *dev = plane->dev; > struct drm_i915_private *dev_priv = dev->dev_private; > struct intel_crtc *intel_crtc = to_intel_crtc(crtc); > - enum pipe pipe = intel_crtc->pipe; > struct drm_i915_gem_object *obj = intel_fb_obj(fb); > struct intel_plane *intel_plane = to_intel_plane(plane); > struct drm_rect *src = &state->src; > + enum pipe pipe = intel_plane->pipe; > > - crtc->primary->fb = fb; > + if (!fb) { > + /* > + * 'prepare' is never called when plane is being disabled, so > + * we need to handle frontbuffer tracking here > + */ > + mutex_lock(&dev->struct_mutex); > + i915_gem_track_fb(intel_fb_obj(plane->fb), NULL, > + INTEL_FRONTBUFFER_PRIMARY(pipe)); > + mutex_unlock(&dev->struct_mutex); > + } > + > + plane->fb = fb; > crtc->x = src->x1 >> 16; > crtc->y = src->y1 >> 16; > > @@ -11897,6 +11871,25 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, > return 0; > } > > +/** > + * intel_disable_plane - disable a plane > + * @plane: plane to disable > + * > + * General disable handler for all plane types. > + */ > +int > +intel_disable_plane(struct drm_plane *plane) > +{ > + if (!plane->fb) > + return 0; > + > + if (WARN_ON(!plane->crtc)) > + return -EINVAL; > + > + return plane->funcs->update_plane(plane, plane->crtc, NULL, > + 0, 0, 0, 0, 0, 0, 0, 0); > +} > + > /* Common destruction function for both primary and cursor planes */ > static void intel_plane_destroy(struct drm_plane *plane) > { > @@ -11907,7 +11900,7 @@ static void intel_plane_destroy(struct drm_plane *plane) > > static const struct drm_plane_funcs intel_primary_plane_funcs = { > .update_plane = intel_update_plane, > - .disable_plane = intel_primary_plane_disable, > + .disable_plane = intel_disable_plane, > .destroy = intel_plane_destroy, > .set_property = intel_plane_set_property > }; > @@ -11962,18 +11955,6 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, > } > > static int > -intel_cursor_plane_disable(struct drm_plane *plane) > -{ > - if (!plane->fb) > - return 0; > - > - BUG_ON(!plane->crtc); > - > - return plane->funcs->update_plane(plane, plane->crtc, NULL, > - 0, 0, 0, 0, 0, 0, 0, 0); > -} > - > -static int > intel_check_cursor_plane(struct drm_plane *plane, > struct intel_plane_state *state) > { > @@ -12097,7 +12078,7 @@ update: > > static const struct drm_plane_funcs intel_cursor_plane_funcs = { > .update_plane = intel_update_plane, > - .disable_plane = intel_cursor_plane_disable, > + .disable_plane = intel_disable_plane, > .destroy = intel_plane_destroy, > .set_property = intel_plane_set_property, > }; > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h > index f7b6619..53b696e 100644 > --- a/drivers/gpu/drm/i915/intel_drv.h > +++ b/drivers/gpu/drm/i915/intel_drv.h > @@ -1020,6 +1020,7 @@ int intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, > unsigned int crtc_w, unsigned int crtc_h, > uint32_t src_x, uint32_t src_y, > uint32_t src_w, uint32_t src_h); > +int intel_disable_plane(struct drm_plane *plane); > > /* intel_dp_mst.c */ > int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id); > @@ -1201,7 +1202,6 @@ int intel_plane_set_property(struct drm_plane *plane, > struct drm_property *prop, > uint64_t val); > int intel_plane_restore(struct drm_plane *plane); > -void intel_plane_disable(struct drm_plane *plane); > int intel_sprite_set_colorkey(struct drm_device *dev, void *data, > struct drm_file *file_priv); > int intel_sprite_get_colorkey(struct drm_device *dev, void *data, > diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c > index bfd5270..bc5834b 100644 > --- a/drivers/gpu/drm/i915/intel_sprite.c > +++ b/drivers/gpu/drm/i915/intel_sprite.c > @@ -1109,7 +1109,12 @@ intel_check_sprite_plane(struct drm_plane *plane, > const struct drm_rect *clip = &state->clip; > int hscale, vscale; > int max_scale, min_scale; > - int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); > + int pixel_size; > + > + if (!fb) { > + state->visible = false; > + return 0; > + } > > /* Don't modify another pipe's plane */ > if (intel_plane->pipe != intel_crtc->pipe) { > @@ -1232,6 +1237,7 @@ intel_check_sprite_plane(struct drm_plane *plane, > if (src_w < 3 || src_h < 3) > state->visible = false; > > + pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); > width_bytes = ((src_x * pixel_size) & 63) + > src_w * pixel_size; > > @@ -1276,6 +1282,17 @@ intel_commit_sprite_plane(struct drm_plane *plane, > bool primary_enabled; > > /* > + * 'prepare' is never called when plane is being disabled, so we need > + * to handle frontbuffer tracking here > + */ > + if (!fb) { > + mutex_lock(&dev->struct_mutex); > + i915_gem_track_fb(intel_fb_obj(plane->fb), NULL, > + INTEL_FRONTBUFFER_SPRITE(pipe)); > + mutex_unlock(&dev->struct_mutex); > + } > + > + /* > * If the sprite is completely covering the primary plane, > * we can disable the primary and save power. > */ > @@ -1327,50 +1344,6 @@ intel_commit_sprite_plane(struct drm_plane *plane, > } > } > > -static int > -intel_disable_plane(struct drm_plane *plane) > -{ > - struct drm_device *dev = plane->dev; > - struct intel_plane *intel_plane = to_intel_plane(plane); > - struct intel_crtc *intel_crtc; > - enum pipe pipe; > - > - if (!plane->fb) > - return 0; > - > - if (WARN_ON(!plane->crtc)) > - return -EINVAL; > - > - intel_crtc = to_intel_crtc(plane->crtc); > - pipe = intel_crtc->pipe; > - > - if (intel_crtc->active) { > - bool primary_was_enabled = intel_crtc->primary_enabled; > - > - intel_crtc->primary_enabled = true; > - > - intel_plane->disable_plane(plane, plane->crtc); > - > - if (!primary_was_enabled && intel_crtc->primary_enabled) > - intel_post_enable_primary(plane->crtc); > - } > - > - if (intel_plane->obj) { > - if (intel_crtc->active) > - intel_wait_for_vblank(dev, intel_plane->pipe); > - > - mutex_lock(&dev->struct_mutex); > - intel_unpin_fb_obj(intel_plane->obj); > - i915_gem_track_fb(intel_plane->obj, NULL, > - INTEL_FRONTBUFFER_SPRITE(pipe)); > - mutex_unlock(&dev->struct_mutex); > - > - intel_plane->obj = NULL; > - } > - > - return 0; > -} > - > static void intel_destroy_plane(struct drm_plane *plane) > { > struct intel_plane *intel_plane = to_intel_plane(plane); > @@ -1478,14 +1451,6 @@ int intel_plane_restore(struct drm_plane *plane) > intel_plane->src_w, intel_plane->src_h); > } > > -void intel_plane_disable(struct drm_plane *plane) > -{ > - if (!plane->crtc || !plane->fb) > - return; > - > - intel_disable_plane(plane); > -} > - > static const struct drm_plane_funcs intel_plane_funcs = { > .update_plane = intel_update_plane, > .disable_plane = intel_disable_plane, >
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index d13015c..eb422bf 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4060,7 +4060,7 @@ static void intel_disable_planes(struct drm_crtc *crtc) drm_for_each_legacy_plane(plane, &dev->mode_config.plane_list) { intel_plane = to_intel_plane(plane); if (intel_plane->pipe == pipe) - intel_plane_disable(&intel_plane->base); + plane->funcs->disable_plane(plane); } } @@ -11605,43 +11605,6 @@ static void intel_shared_dpll_init(struct drm_device *dev) BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS); } -static int -intel_primary_plane_disable(struct drm_plane *plane) -{ - struct drm_device *dev = plane->dev; - struct intel_crtc *intel_crtc; - - if (!plane->fb) - return 0; - - BUG_ON(!plane->crtc); - - intel_crtc = to_intel_crtc(plane->crtc); - - /* - * Even though we checked plane->fb above, it's still possible that - * the primary plane has been implicitly disabled because the crtc - * coordinates given weren't visible, or because we detected - * that it was 100% covered by a sprite plane. Or, the CRTC may be - * off and we've set a fb, but haven't actually turned on the CRTC yet. - * In either case, we need to unpin the FB and let the fb pointer get - * updated, but otherwise we don't need to touch the hardware. - */ - if (intel_crtc->primary_enabled) { - intel_crtc_wait_for_pending_flips(plane->crtc); - intel_disable_primary_hw_plane(plane, plane->crtc); - } - - mutex_lock(&dev->struct_mutex); - i915_gem_track_fb(intel_fb_obj(plane->fb), NULL, - INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe)); - intel_unpin_fb_obj(intel_fb_obj(plane->fb)); - mutex_unlock(&dev->struct_mutex); - plane->fb = NULL; - - return 0; -} - /** * intel_prepare_plane_fb - Prepare fb for usage on plane * @plane: drm plane to prepare for @@ -11745,8 +11708,8 @@ intel_check_primary_plane(struct drm_plane *plane, if (ret) return ret; - intel_crtc_wait_for_pending_flips(crtc); - if (intel_crtc_has_pending_flip(crtc)) { + intel_crtc_wait_for_pending_flips(plane->crtc); + if (intel_crtc_has_pending_flip(plane->crtc)) { DRM_ERROR("pipe is still busy with an old pageflip\n"); return -EBUSY; } @@ -11763,12 +11726,23 @@ intel_commit_primary_plane(struct drm_plane *plane, struct drm_device *dev = plane->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - enum pipe pipe = intel_crtc->pipe; struct drm_i915_gem_object *obj = intel_fb_obj(fb); struct intel_plane *intel_plane = to_intel_plane(plane); struct drm_rect *src = &state->src; + enum pipe pipe = intel_plane->pipe; - crtc->primary->fb = fb; + if (!fb) { + /* + * 'prepare' is never called when plane is being disabled, so + * we need to handle frontbuffer tracking here + */ + mutex_lock(&dev->struct_mutex); + i915_gem_track_fb(intel_fb_obj(plane->fb), NULL, + INTEL_FRONTBUFFER_PRIMARY(pipe)); + mutex_unlock(&dev->struct_mutex); + } + + plane->fb = fb; crtc->x = src->x1 >> 16; crtc->y = src->y1 >> 16; @@ -11897,6 +11871,25 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, return 0; } +/** + * intel_disable_plane - disable a plane + * @plane: plane to disable + * + * General disable handler for all plane types. + */ +int +intel_disable_plane(struct drm_plane *plane) +{ + if (!plane->fb) + return 0; + + if (WARN_ON(!plane->crtc)) + return -EINVAL; + + return plane->funcs->update_plane(plane, plane->crtc, NULL, + 0, 0, 0, 0, 0, 0, 0, 0); +} + /* Common destruction function for both primary and cursor planes */ static void intel_plane_destroy(struct drm_plane *plane) { @@ -11907,7 +11900,7 @@ static void intel_plane_destroy(struct drm_plane *plane) static const struct drm_plane_funcs intel_primary_plane_funcs = { .update_plane = intel_update_plane, - .disable_plane = intel_primary_plane_disable, + .disable_plane = intel_disable_plane, .destroy = intel_plane_destroy, .set_property = intel_plane_set_property }; @@ -11962,18 +11955,6 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, } static int -intel_cursor_plane_disable(struct drm_plane *plane) -{ - if (!plane->fb) - return 0; - - BUG_ON(!plane->crtc); - - return plane->funcs->update_plane(plane, plane->crtc, NULL, - 0, 0, 0, 0, 0, 0, 0, 0); -} - -static int intel_check_cursor_plane(struct drm_plane *plane, struct intel_plane_state *state) { @@ -12097,7 +12078,7 @@ update: static const struct drm_plane_funcs intel_cursor_plane_funcs = { .update_plane = intel_update_plane, - .disable_plane = intel_cursor_plane_disable, + .disable_plane = intel_disable_plane, .destroy = intel_plane_destroy, .set_property = intel_plane_set_property, }; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index f7b6619..53b696e 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1020,6 +1020,7 @@ int intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, unsigned int crtc_w, unsigned int crtc_h, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h); +int intel_disable_plane(struct drm_plane *plane); /* intel_dp_mst.c */ int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id); @@ -1201,7 +1202,6 @@ int intel_plane_set_property(struct drm_plane *plane, struct drm_property *prop, uint64_t val); int intel_plane_restore(struct drm_plane *plane); -void intel_plane_disable(struct drm_plane *plane); int intel_sprite_set_colorkey(struct drm_device *dev, void *data, struct drm_file *file_priv); int intel_sprite_get_colorkey(struct drm_device *dev, void *data, diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index bfd5270..bc5834b 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1109,7 +1109,12 @@ intel_check_sprite_plane(struct drm_plane *plane, const struct drm_rect *clip = &state->clip; int hscale, vscale; int max_scale, min_scale; - int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); + int pixel_size; + + if (!fb) { + state->visible = false; + return 0; + } /* Don't modify another pipe's plane */ if (intel_plane->pipe != intel_crtc->pipe) { @@ -1232,6 +1237,7 @@ intel_check_sprite_plane(struct drm_plane *plane, if (src_w < 3 || src_h < 3) state->visible = false; + pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); width_bytes = ((src_x * pixel_size) & 63) + src_w * pixel_size; @@ -1276,6 +1282,17 @@ intel_commit_sprite_plane(struct drm_plane *plane, bool primary_enabled; /* + * 'prepare' is never called when plane is being disabled, so we need + * to handle frontbuffer tracking here + */ + if (!fb) { + mutex_lock(&dev->struct_mutex); + i915_gem_track_fb(intel_fb_obj(plane->fb), NULL, + INTEL_FRONTBUFFER_SPRITE(pipe)); + mutex_unlock(&dev->struct_mutex); + } + + /* * If the sprite is completely covering the primary plane, * we can disable the primary and save power. */ @@ -1327,50 +1344,6 @@ intel_commit_sprite_plane(struct drm_plane *plane, } } -static int -intel_disable_plane(struct drm_plane *plane) -{ - struct drm_device *dev = plane->dev; - struct intel_plane *intel_plane = to_intel_plane(plane); - struct intel_crtc *intel_crtc; - enum pipe pipe; - - if (!plane->fb) - return 0; - - if (WARN_ON(!plane->crtc)) - return -EINVAL; - - intel_crtc = to_intel_crtc(plane->crtc); - pipe = intel_crtc->pipe; - - if (intel_crtc->active) { - bool primary_was_enabled = intel_crtc->primary_enabled; - - intel_crtc->primary_enabled = true; - - intel_plane->disable_plane(plane, plane->crtc); - - if (!primary_was_enabled && intel_crtc->primary_enabled) - intel_post_enable_primary(plane->crtc); - } - - if (intel_plane->obj) { - if (intel_crtc->active) - intel_wait_for_vblank(dev, intel_plane->pipe); - - mutex_lock(&dev->struct_mutex); - intel_unpin_fb_obj(intel_plane->obj); - i915_gem_track_fb(intel_plane->obj, NULL, - INTEL_FRONTBUFFER_SPRITE(pipe)); - mutex_unlock(&dev->struct_mutex); - - intel_plane->obj = NULL; - } - - return 0; -} - static void intel_destroy_plane(struct drm_plane *plane) { struct intel_plane *intel_plane = to_intel_plane(plane); @@ -1478,14 +1451,6 @@ int intel_plane_restore(struct drm_plane *plane) intel_plane->src_w, intel_plane->src_h); } -void intel_plane_disable(struct drm_plane *plane) -{ - if (!plane->crtc || !plane->fb) - return; - - intel_disable_plane(plane); -} - static const struct drm_plane_funcs intel_plane_funcs = { .update_plane = intel_update_plane, .disable_plane = intel_disable_plane,