[PATCH v6 7/9] drm/msm/dpu: add support for virtual planes
Dmitry Baryshkov
dmitry.baryshkov at linaro.org
Fri Nov 1 20:53:30 UTC 2024
On Fri, Nov 01, 2024 at 01:37:03PM -0700, Abhinav Kumar wrote:
>
>
> On 10/31/2024 2:03 PM, Dmitry Baryshkov wrote:
> > On Thu, Oct 31, 2024 at 01:06:34PM -0700, Abhinav Kumar wrote:
> > >
> > >
> > > On 10/31/2024 8:11 AM, Dmitry Baryshkov wrote:
> > > > Hi Abhinav,
> > > >
> > > > On Wed, 30 Oct 2024 at 21:26, Abhinav Kumar <quic_abhinavk at quicinc.com> wrote:
> > > > >
> > > > >
> > > > >
> > > > > On 10/30/2024 3:48 AM, Dmitry Baryshkov wrote:
> > > > > > On Tue, Oct 29, 2024 at 02:30:12PM -0700, Abhinav Kumar wrote:
> > > > > > >
> > > > > > >
> > > > > > > On 10/24/2024 5:20 PM, Dmitry Baryshkov wrote:
> > > > > > > > Only several SSPP blocks support such features as YUV output or scaling,
> > > > > > > > thus different DRM planes have different features. Properly utilizing
> > > > > > > > all planes requires the attention of the compositor, who should
> > > > > > > > prefer simpler planes to YUV-supporting ones. Otherwise it is very easy
> > > > > > > > to end up in a situation when all featureful planes are already
> > > > > > > > allocated for simple windows, leaving no spare plane for YUV playback.
> > > > > > > >
> > > > > > > > To solve this problem make all planes virtual. Each plane is registered
> > > > > > > > as if it supports all possible features, but then at the runtime during
> > > > > > > > the atomic_check phase the driver selects backing SSPP block for each
> > > > > > > > plane.
> > > > > > > >
> > > > > > > > As the planes are attached to the CRTC and not the encoder, the SSPP
> > > > > > > > blocks are also allocated per CRTC ID (all other resources are currently
> > > > > > > > allocated per encoder ID). This also matches the hardware requirement,
> > > > > > > > where both rectangles of a single SSPP can only be used with the LM
> > > > > > > > pair.
> > > > > > > >
> > > > > > > > Note, this does not provide support for using two different SSPP blocks
> > > > > > > > for a single plane or using two rectangles of an SSPP to drive two
> > > > > > > > planes. Each plane still gets its own SSPP and can utilize either a solo
> > > > > > > > rectangle or both multirect rectangles depending on the resolution.
> > > > > > > >
> > > > > > > > Note #2: By default support for virtual planes is turned off and the
> > > > > > > > driver still uses old code path with preallocated SSPP block for each
> > > > > > > > plane. To enable virtual planes, pass 'msm.dpu_use_virtual_planes=1'
> > > > > > > > kernel parameter.
> > > > > > > >
> > > > > > > > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
> > > > > > > > ---
> > > > > > > > drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 50 +++++++
> > > > > > > > drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 10 +-
> > > > > > > > drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 4 +
> > > > > > > > drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 237 ++++++++++++++++++++++++++----
> > > > > > > > drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h | 16 ++
> > > > > > > > drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 68 +++++++++
> > > > > > > > drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 27 ++++
> > > > > > > > 7 files changed, 383 insertions(+), 29 deletions(-)
> > > > > > > >
> > > > > > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > > > > > > > index 58595dcc3889..a7eea094aa14 100644
> > > > > > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > > > > > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > > > > > > > @@ -1166,6 +1166,49 @@ static bool dpu_crtc_needs_dirtyfb(struct drm_crtc_state *cstate)
> > > > > > > > return false;
> > > > > > > > }
> > > > > > > > +static int dpu_crtc_reassign_planes(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state)
> > > > > > > > +{
> > > > > > > > + int total_planes = crtc->dev->mode_config.num_total_plane;
> > > > > > > > + struct drm_atomic_state *state = crtc_state->state;
> > > > > > > > + struct dpu_global_state *global_state;
> > > > > > > > + struct drm_plane_state **states;
> > > > > > > > + struct drm_plane *plane;
> > > > > > > > + int ret;
> > > > > > > > +
> > > > > > > > + global_state = dpu_kms_get_global_state(crtc_state->state);
> > > > > > > > + if (IS_ERR(global_state))
> > > > > > > > + return PTR_ERR(global_state);
> > > > > > > > +
> > > > > > > > + dpu_rm_release_all_sspp(global_state, crtc);
> > > > > > > > +
> > > > > > > > + if (!crtc_state->enable)
> > > > > > > > + return 0;
> > > > > > > > +
> > > > > > > > + states = kcalloc(total_planes, sizeof(*states), GFP_KERNEL);
> > > > > > > > + if (!states)
> > > > > > > > + return -ENOMEM;
> > > > > > > > +
> > > > > > > > + drm_atomic_crtc_state_for_each_plane(plane, crtc_state) {
> > > > > > > > + struct drm_plane_state *plane_state =
> > > > > > > > + drm_atomic_get_plane_state(state, plane);
> > > > > > > > +
> > > > > > > > + if (IS_ERR(plane_state)) {
> > > > > > > > + ret = PTR_ERR(plane_state);
> > > > > > > > + goto done;
> > > > > > > > + }
> > > > > > > > +
> > > > > > > > + states[plane_state->normalized_zpos] = plane_state;
> > > > > > > > + }
> > > > > > > > +
> > > > > > > > + ret = dpu_assign_plane_resources(global_state, state, crtc, states, total_planes);
> > > > > > > > +
> > > > > > > > +done:
> > > > > > > > + kfree(states);
> > > > > > > > + return ret;
> > > > > > > > +
> > > > > > > > + return 0;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
> > > > > > > > struct drm_atomic_state *state)
> > > > > > > > {
> > > > > > > > @@ -1181,6 +1224,13 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
> > > > > > > > bool needs_dirtyfb = dpu_crtc_needs_dirtyfb(crtc_state);
> > > > > > > > + if (dpu_use_virtual_planes &&
> > > > > > > > + (crtc_state->planes_changed || crtc_state->zpos_changed)) {
> > > > > > > > + rc = dpu_crtc_reassign_planes(crtc, crtc_state);
> > > > > > > > + if (rc < 0)
> > > > > > > > + return rc;
> > > > > > > > + }
> > > > > > >
> > > > > > > planes_changed is set only for format changes . Will it cover all
> > > > > > > needs_modeset cases?
> > > > > > >
> > > > > > > OR do we also need to set planes_changed when
> > > > > > > drm_atomic_crtc_needs_modeset()?
> > > > > > >
> > > > > > > Unless I am missing something, I think we have to otherwise sspp
> > > > > > > reallocation wont happen in modeset cases.
> > > > > >
> > > > > > I was depending on the planes being included in the state by the client.
> > > > > > I don't think we really care about the modeset per se. We care about
> > > > > > plane size changes. And changing the size means that the plane is
> > > > > > included into the commit.
> > > > > >
> > > > >
> > > > > The global state mapping for SSPPs has to be cleared across modesets
> > > > > IMO. This is no different from us calling dpu_rm_release() today in
> > > > > dpu_encoder_virt_atomic_check(). I just am not sure whether
> > > > > planes_changed will cover all modeset conditions.
> > > >
> > > > We clear other resources, because they depend on the CRTC resolution.
> > > > Planes do not. Well, not until the quadpipe is in play.
> > > > SSPPs (currently) should be reallocated only if the _plane_'s
> > > > resolution change. If we have a modeset which involves CRTC resolution
> > > > change, but not the plane's size change, there is no need to
> > > > reallocate SSPPs.
> > > >
> > >
> > > In dpu_encoder_helper_phys_cleanup(), the SSPPs attached to all LMs are
> > > removed so clearing all the hardware. If the global state is still going to
> > > retain the older configuration not reflecting this clear, it seems incorrect
> > > to me. Thats why I was thinking of clearing all the SSPP mapping in
> > > disable() or in the modeset prior to the disable as technically thats being
> > > done in HW today anyway.
> > >
> > > During the next atomic check, the planes in the crtc's current state will
> > > get re-attached and programmed to the blend stages. So this clearing of
> > > global state is reflecting the current state of the corresponding hardware.
> >
> > The global state tracks resource allocation. If we clear the resources
> > in the disable() path, we have no way to know which SSPP blocks were
> > assigned to us in the corresponding enable() call path. There is no
> > guarantee that there will be an atomic_check() between disable() and
> > enable().
> >
>
> So I had suggested clearing in disable() because we did not come to an
> agreement to doing it in atomic_check() just a few comments earlier.
>
> Doing it in disable() is not right. I agree with that part now as we should
> not be touching the state after atomic_check() phase.
>
> That brings me back to my original question. With the planes_changed check
> in atomic_check how can we guarantee that global state SSPP allocation is
> freed and allocated again across a disable() / enable() cycle? Can you pls
> confirm whether this is happening or not across a hotplug and suspend/resume
> cycle?
disable() / enable() on which object? Because CRTC, if it
needs_modeset() || crtc_needs_disable() absolutely can go through a
disable / enable cycle, it doesn't require SSPP reallocation at all.
But maybe it's easier to just have drm_atomic_crtc_needs_modeset(). Will
that make it better for you?
>
>
> > >
> > > > >
> > > > > Were you able to confirm whether the mapping gets cleared across
> > > > > hotplugs or suspend/resumes? If so, it would confirm whether
> > > > > planes_changed covers these aspects. Although, I think clearing should
> > > > > be more explicit.
> > > >
> > > > I will check that tomorrow.
> > > >
> > > > > Another option could be for you to call dpu_rm_release_all_sspp() in
> > > > > dpu_crtc_disable(). So that across a disable and enable we have a clear
> > > > > mapping table. WDYT?
> > > >
> > > > Absolutely no. The RM state should only be changed when other object's
> > > > state change - in atomic_check(). After that it is mostly r/o.
> > > > enabling/disabling the resource shouldn't change resource assignment
> > > > at all.
> > > >
>
> Ack but please check above.
>
> > > > >
> > > > > > >
> > > > > > > Overall, mainly we want to make sure SSPPs are re-assigned when:
> > > > > > >
> > > > > >
> > > > > > 0) plane size changes
> > > > > > > > 1) format changes (RGB to YUV and vice-versa)
> > > > > > > 2) Any modesets
> > > > > >
> > > > > > No
> > > > >
> > > > > I am not able to follow why this is different from any global state
> > > > > mapping of other HW blocks that we do across modesets.
> > > >
> > > > DIfferent lifecycle requirements, I'd say.
> > > >
> > > > >
> > > > > >
> > > > > > > 3) Any disable/enable without modeset like connectors changed as SSPPs are
> > > > > > > changing outputs there.
> > > > > >
> > > > > > Absolutely no, the logic should be the same as active vs enabled for
> > > > > > CRTCs. Realloc resources only if the plane itself gets disabled or
> > > > > > enabled. In all other cases the set of SSPP blocks should stay
> > > > > > untouched.
> > > > > >
> > > > >
> > > > > I am going to re-visit this later perhaps but if we incorporate my above
> > > > > suggestion of clearing the mapping in disable() I will be partially
> > > > > satisfied.
> > > >
> > > > No, resource mapping can not be cleaned in disable(). We do not do
> > > > that for any other resource kind.
> > > >
> > >
> > > That gets handled with the needs_modeset part today which is calling the
> > > dpu_rm_release().
> >
> > In atomic_check() path, not in the disable() path.
> >
> > >
> > > > >
> > > > > > >
> > > > > > > If we are covered for all these, let me know.
> > > > > > >
> > > > > > > > +
> > > > > > > > if (!crtc_state->enable || !drm_atomic_crtc_effectively_active(crtc_state)) {
> > > > > > > > DRM_DEBUG_ATOMIC("crtc%d -> enable %d, active %d, skip atomic_check\n",
> > > > > > > > crtc->base.id, crtc_state->enable,
> > > > > > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> > > > > > > > index 15679dd50c66..70757d876cc3 100644
> > > > > > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> > > > > > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> > > > > > > > @@ -51,6 +51,9 @@
> > > > > > > > #define DPU_DEBUGFS_DIR "msm_dpu"
> > > > > > > > #define DPU_DEBUGFS_HWMASKNAME "hw_log_mask"
> > > > > > > > +bool dpu_use_virtual_planes;
> > > > > > > > +module_param(dpu_use_virtual_planes, bool, 0);
> > > > > > > > +
> > > > > > > > static int dpu_kms_hw_init(struct msm_kms *kms);
> > > > > > > > static void _dpu_kms_mmu_destroy(struct dpu_kms *dpu_kms);
> > > > > > > > @@ -814,8 +817,11 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms)
> > > > > > > > type, catalog->sspp[i].features,
> > > > > > > > catalog->sspp[i].features & BIT(DPU_SSPP_CURSOR));
> > > > > > > > - plane = dpu_plane_init(dev, catalog->sspp[i].id, type,
> > > > > > > > - (1UL << max_crtc_count) - 1);
> > > > > > > > + if (dpu_use_virtual_planes)
> > > > > > > > + plane = dpu_plane_init_virtual(dev, type, (1UL << max_crtc_count) - 1);
> > > > > > > > + else
> > > > > > > > + plane = dpu_plane_init(dev, catalog->sspp[i].id, type,
> > > > > > > > + (1UL << max_crtc_count) - 1);
> > > > > > > > if (IS_ERR(plane)) {
> > > > > > > > DPU_ERROR("dpu_plane_init failed\n");
> > > > > > > > ret = PTR_ERR(plane);
> > > > > > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > > > > > > > index 935ff6fd172c..479d4c172290 100644
> > > > > > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > > > > > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > > > > > > > @@ -54,6 +54,8 @@
> > > > > > > > #define ktime_compare_safe(A, B) \
> > > > > > > > ktime_compare(ktime_sub((A), (B)), ktime_set(0, 0))
> > > > > > > > +extern bool dpu_use_virtual_planes;
> > > > > > > > +
> > > > > > > > struct dpu_kms {
> > > > > > > > struct msm_kms base;
> > > > > > > > struct drm_device *dev;
> > > > > > > > @@ -128,6 +130,8 @@ struct dpu_global_state {
> > > > > > > > uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0];
> > > > > > > > uint32_t dsc_to_enc_id[DSC_MAX - DSC_0];
> > > > > > > > uint32_t cdm_to_enc_id;
> > > > > > > > +
> > > > > > > > + uint32_t sspp_to_crtc_id[SSPP_MAX - SSPP_NONE];
> > > > > > > > };
> > > > > > >
> > > > > > > This is the part which now looks odd and can be managed with rebase I guess.
> > > > > > >
> > > > > > > Are you planning to pull in the move resource allocation to crtc_id changes
> > > > > > > first before this part? IOW, rebase this change on top of that?
> > > > > >
> > > > > > No. I do not. If you remember, several revisions ago the enc_id ->
> > > > > > crtc_id was a part of the series, but we both agreed to drop it since it
> > > > > > was not required for virtual planes. As such, I plan to land this one
> > > > > > first (yes, having some of the resources tracked basing on enc_id and
> > > > > > SSPP is tracked basing on crtc_id).
> > > > > >
> > > > >
> > > > > Yes, I am not asking whether you will be absorbing those changes into
> > > > > this series. Even I would not suggest doing that.
> > > > >
> > > > > I was asking whether you will merge the crtc_id based tracking first and
> > > > > then apply this on top of that and not the other way around.
> > > > >
> > > > > Because with this specific line I am certain it will conflict as both
> > > > > the series touch struct dpu_global_state.
> > > >
> > > > They touch different parts of it. So I'd prefer to land this one first
> > > > and then land using crtc_id for mapping.
> > > >
> > >
> > > I am okay to fixup any other issues which arise later on because we have the
> > > modparam protection anyway but I think validating suspend/resume and hotplug
> > > to ensure no black screens is required. If those two cases work fine on your
> > > end, we can proceed.
> >
> > I have been validating these changes with hotplug events, yes. I wasn't
> > checking the suspend/resume, but that's broken anyway, until we land
> > https://patchwork.freedesktop.org/patch/606931/?series=135908&rev=2
> >
>
> Can you pls confirm once whether the global state mapping gets freed across
> crtc disable/enable cycle with the planes_changed check? I think it has to.
I think you are asking the question from the wrong side. What kind of
commit leads to that CRTC disable/enable cycle?
>
> Other items are closed so snipping out below.
--
With best wishes
Dmitry
More information about the dri-devel
mailing list