Skip to content

Commit

Permalink
drm/msm/dpu: add support for virtual planes
Browse files Browse the repository at this point in the history
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.

Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Patchwork: https://patchwork.freedesktop.org/patch/629022/
Link: https://lore.kernel.org/r/20241215-dpu-virtual-wide-v8-1-65221f213ce1@linaro.org
  • Loading branch information
Dmitry Baryshkov committed Dec 15, 2024
1 parent 8a570c9 commit 774bcfb
Show file tree
Hide file tree
Showing 7 changed files with 390 additions and 32 deletions.
50 changes: 50 additions & 0 deletions drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1189,6 +1189,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)
{
Expand All @@ -1204,6 +1247,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;
}

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,
Expand Down
10 changes: 8 additions & 2 deletions drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -829,8 +832,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);
Expand Down
4 changes: 4 additions & 0 deletions drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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];
};

struct dpu_global_state
Expand Down
Loading

0 comments on commit 774bcfb

Please sign in to comment.