[PATCHv4 06/13] drm: Add primary plane helpers (v2)

Rob Clark robdclark at gmail.com
Mon Mar 31 18:04:30 PDT 2014


On Fri, Mar 28, 2014 at 4:32 AM, Daniel Vetter <daniel at ffwll.ch> wrote:
>
>> +     /*
>> +      * set_config() adjusts crtc->primary->fb; however the DRM setplane
>> +      * code that called us expects to handle the framebuffer update and
>> +      * reference counting; save and restore the current fb before
>> +      * calling it.
>> +      *
>> +      * N.B., we call set_config() directly here rather than using
>> +      * drm_mode_set_config_internal.  We're reprogramming the same
>> +      * connectors that were already in use, so we shouldn't need the extra
>> +      * cross-CRTC fb refcounting to accomodate stealing connectors.
>> +      * drm_mode_setplane() already handles the basic refcounting for the
>> +      * framebuffers involved in this operation.
>
> Wrong. The current crtc helper logic disables all disconnected connectors
> forcefully on each set_config. Nope, I didn't make those semantics ... So
> I think we need to think a bit harder here again.

Hmm, I'm not really seeing the problem.  The worst setplane could do
is enable a crtc which otherwise already has an encoder+connector
pointing to it.  Which would mean that encoder+connector could not be
pointing to another crtc.

So yeah, we'll end up calling dpms(OFF) on a bunch of stuff that is
already off.. is that a problem?

>
> See drm_helper_disable_unused_functions.
>
>> +      */
>> +     tmpfb = plane->fb;
>> +     ret = crtc->funcs->set_config(&set);
>> +     plane->fb = tmpfb;
>> +
>> +     kfree(connector_list);
>> +     return ret;
>> +}
>> +EXPORT_SYMBOL(drm_primary_helper_update);
>> +
>> +/**
>> + * drm_primary_helper_disable() - Helper for primary plane disable
>> + * @plane: plane to disable
>> + *
>> + * Provides a default plane disable handler for primary planes.  This is handler
>> + * is called in response to a userspace SetPlane operation on the plane with a
>> + * NULL framebuffer parameter.  We call the driver's modeset handler with a NULL
>> + * framebuffer to disable the CRTC if no other planes are currently enabled.
>> + * If other planes are still enabled on the same CRTC, we return -EBUSY.
>> + *
>> + * Note that some hardware may be able to disable the primary plane without
>> + * disabling the whole CRTC.  Drivers for such hardware should provide their
>> + * own disable handler that disables just the primary plane (and they'll likely
>> + * need to provide their own update handler as well to properly re-enable a
>> + * disabled primary plane).
>> + *
>> + * RETURNS:
>> + * Zero on success, error code on failure
>> + */
>> +int drm_primary_helper_disable(struct drm_plane *plane)
>> +{
>> +     struct drm_plane *p;
>> +     struct drm_mode_set set = {
>> +             .crtc = plane->crtc,
>> +             .fb = NULL,
>> +     };
>> +
>> +     if (plane->crtc == NULL || plane->fb == NULL)
>> +             /* Already disabled */
>> +             return 0;
>> +
>> +     list_for_each_entry(p, &plane->dev->mode_config.plane_list, head)
>> +             if (p != plane && p->fb) {
>> +                     DRM_DEBUG_KMS("Cannot disable primary plane while other planes are still active on CRTC.\n");
>> +                     return -EBUSY;
>> +             }
>> +
>> +     /*
>> +      * N.B.  We call set_config() directly here rather than
>> +      * drm_mode_set_config_internal() since drm_mode_setplane() already
>> +      * handles the basic refcounting and we don't need the special
>> +      * cross-CRTC refcounting (no chance of stealing connectors from
>> +      * other CRTC's with this update).
>
> Same comment as above applies. Calling ->set_config is considered harmful
> ... Maybe we need to add another wrapper here for the primary plane
> helpers to wrap this all up safely?


actually, again, I think calling .set_config() directly here is the
correct thing.  There should be no connector/encoder changes.  and the
drm_mode_set_config_internal() refcounting would be wrong for
drm_mode_setplane().  In the helpers he undoes the plane->fb update
done by the driver in .set_config() so that drm_mode_setplane() dtrt..


As an aside, that inconsistency between who updates the fb ptr between
setcrtc and setplane has been bothering me for a while now with the
atomic stuff.  Maybe it's just the OCD talking, but I'd *really* like
to clean that up.  The rough thinking I have, with the atomic stuff we
introduce a second fb pointer (and reference) in the state object.  So
initially we have:

   plane->fb    ---   current rules
   plane->state->fb   ---   immutable, set to new incoming fb before
calling in to driver.. drm core manages the refcnt, read-only access
for the driver

what I'd like to do is request that all drivers add their own internal
scanout references, etc.  And we eventually remove plane->fb when no
one still references it.  The outgoing state object will hold a ref to
old_fb until after we return from calling in to the driver.  The only
thing left is for each driver to (if it cannot cancel scanout
mid-frame) hold a reference until next vblank.

BR,
-R


More information about the dri-devel mailing list