On 6/26/2024 2:46 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 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@xxxxxxxxxx> --- 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 | 236 ++++++++++++++++++++++++++---- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h | 16 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 77 ++++++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 27 ++++ 7 files changed, 391 insertions(+), 29 deletions(-)
<snip>
+struct dpu_hw_sspp *dpu_rm_reserve_sspp(struct dpu_rm *rm, + struct dpu_global_state *global_state, + struct drm_crtc *crtc, + struct dpu_rm_sspp_requirements *reqs) +{ + uint32_t crtc_id = crtc->base.id; + unsigned int weight, best_weight = UINT_MAX; + struct dpu_hw_sspp *hw_sspp; + unsigned long mask = 0; + int i, best_idx = -1; + + /* + * Don't take cursor feature into consideration until there is proper support for SSPP_CURSORn. + */ + mask |= BIT(DPU_SSPP_CURSOR); + + if (reqs->scale) + mask |= BIT(DPU_SSPP_SCALER_RGB) | + BIT(DPU_SSPP_SCALER_QSEED2) | + BIT(DPU_SSPP_SCALER_QSEED3_COMPATIBLE); + + if (reqs->yuv) + mask |= BIT(DPU_SSPP_CSC) | + BIT(DPU_SSPP_CSC_10BIT); + + if (reqs->rot90) + mask |= BIT(DPU_SSPP_INLINE_ROTATION); + + for (i = 0; i < ARRAY_SIZE(rm->hw_sspp); i++) { + if (!rm->hw_sspp[i]) + continue; + + if (global_state->sspp_to_crtc_id[i]) + continue; + + hw_sspp = rm->hw_sspp[i]; + + /* skip incompatible planes */ + if (reqs->scale && !hw_sspp->cap->sblk->scaler_blk.len) + continue; + + if (reqs->yuv && !hw_sspp->cap->sblk->csc_blk.len) + continue; + + if (reqs->rot90 && !(hw_sspp->cap->features & DPU_SSPP_INLINE_ROTATION)) + continue; + + /* + * For non-yuv, non-scaled planes prefer simple (DMA or RGB) + * plane, falling back to VIG only if there are no such planes. + * + * This way we'd leave VIG sspps to be later used for YUV formats. + */ + weight = hweight64(hw_sspp->cap->features & ~mask); + if (weight < best_weight) { + best_weight = weight; + best_idx = i; + } + }
As commented in the earlier version, we need to stop using hweight as a means of identifying the SSPP type and just use type and feature bits instead.