Skip to content

Commit 3ed12a3

Browse files
committed
drm/msm/dpu: allow sharing SSPP between planes
Since SmartDMA planes provide two rectangles, it is possible to use them to drive two different DRM planes, first plane getting the rect_0, another one using rect_1 of the same SSPP. The sharing algorithm is pretty simple, it requires that each of the planes can be driven by the single rectangle and only consecutive planes are considered. Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com> Patchwork: https://patchwork.freedesktop.org/patch/650441/ Link: https://lore.kernel.org/r/20250426-dpu-share-sspp-v7-1-6f4c719e373c@oss.qualcomm.com Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
1 parent 9b565ed commit 3ed12a3

File tree

1 file changed

+130
-26
lines changed

1 file changed

+130
-26
lines changed

drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c

Lines changed: 130 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -915,10 +915,9 @@ static int dpu_plane_atomic_check_nosspp(struct drm_plane *plane,
915915
return 0;
916916
}
917917

918-
static int dpu_plane_is_multirect_parallel_capable(struct dpu_hw_sspp *sspp,
919-
struct dpu_sw_pipe_cfg *pipe_cfg,
920-
const struct msm_format *fmt,
921-
uint32_t max_linewidth)
918+
static int dpu_plane_is_multirect_capable(struct dpu_hw_sspp *sspp,
919+
struct dpu_sw_pipe_cfg *pipe_cfg,
920+
const struct msm_format *fmt)
922921
{
923922
if (drm_rect_width(&pipe_cfg->src_rect) != drm_rect_width(&pipe_cfg->dst_rect) ||
924923
drm_rect_height(&pipe_cfg->src_rect) != drm_rect_height(&pipe_cfg->dst_rect))
@@ -930,17 +929,34 @@ static int dpu_plane_is_multirect_parallel_capable(struct dpu_hw_sspp *sspp,
930929
if (MSM_FORMAT_IS_YUV(fmt))
931930
return false;
932931

933-
if (MSM_FORMAT_IS_UBWC(fmt) &&
934-
drm_rect_width(&pipe_cfg->src_rect) > max_linewidth / 2)
935-
return false;
936-
937932
if (!test_bit(DPU_SSPP_SMART_DMA_V1, &sspp->cap->features) &&
938933
!test_bit(DPU_SSPP_SMART_DMA_V2, &sspp->cap->features))
939934
return false;
940935

941936
return true;
942937
}
943938

939+
static int dpu_plane_is_parallel_capable(struct dpu_sw_pipe_cfg *pipe_cfg,
940+
const struct msm_format *fmt,
941+
uint32_t max_linewidth)
942+
{
943+
if (MSM_FORMAT_IS_UBWC(fmt) &&
944+
drm_rect_width(&pipe_cfg->src_rect) > max_linewidth / 2)
945+
return false;
946+
947+
return true;
948+
}
949+
950+
static int dpu_plane_is_multirect_parallel_capable(struct dpu_hw_sspp *sspp,
951+
struct dpu_sw_pipe_cfg *pipe_cfg,
952+
const struct msm_format *fmt,
953+
uint32_t max_linewidth)
954+
{
955+
return dpu_plane_is_multirect_capable(sspp, pipe_cfg, fmt) &&
956+
dpu_plane_is_parallel_capable(pipe_cfg, fmt, max_linewidth);
957+
}
958+
959+
944960
static int dpu_plane_atomic_check_sspp(struct drm_plane *plane,
945961
struct drm_atomic_state *state,
946962
const struct drm_crtc_state *crtc_state)
@@ -1002,6 +1018,69 @@ static bool dpu_plane_try_multirect_parallel(struct dpu_sw_pipe *pipe, struct dp
10021018
return true;
10031019
}
10041020

1021+
static int dpu_plane_try_multirect_shared(struct dpu_plane_state *pstate,
1022+
struct dpu_plane_state *prev_adjacent_pstate,
1023+
const struct msm_format *fmt,
1024+
uint32_t max_linewidth)
1025+
{
1026+
struct dpu_sw_pipe *pipe = &pstate->pipe;
1027+
struct dpu_sw_pipe *r_pipe = &pstate->r_pipe;
1028+
struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg;
1029+
struct dpu_sw_pipe *prev_pipe = &prev_adjacent_pstate->pipe;
1030+
struct dpu_sw_pipe_cfg *prev_pipe_cfg = &prev_adjacent_pstate->pipe_cfg;
1031+
const struct msm_format *prev_fmt = msm_framebuffer_format(prev_adjacent_pstate->base.fb);
1032+
u16 max_tile_height = 1;
1033+
1034+
if (prev_adjacent_pstate->r_pipe.sspp != NULL ||
1035+
prev_pipe->multirect_mode != DPU_SSPP_MULTIRECT_NONE)
1036+
return false;
1037+
1038+
if (!dpu_plane_is_multirect_capable(pipe->sspp, pipe_cfg, fmt) ||
1039+
!dpu_plane_is_multirect_capable(prev_pipe->sspp, prev_pipe_cfg, prev_fmt))
1040+
return false;
1041+
1042+
if (MSM_FORMAT_IS_UBWC(fmt))
1043+
max_tile_height = max(max_tile_height, fmt->tile_height);
1044+
1045+
if (MSM_FORMAT_IS_UBWC(prev_fmt))
1046+
max_tile_height = max(max_tile_height, prev_fmt->tile_height);
1047+
1048+
r_pipe->multirect_index = DPU_SSPP_RECT_SOLO;
1049+
r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE;
1050+
1051+
r_pipe->sspp = NULL;
1052+
1053+
if (dpu_plane_is_parallel_capable(pipe_cfg, fmt, max_linewidth) &&
1054+
dpu_plane_is_parallel_capable(prev_pipe_cfg, prev_fmt, max_linewidth) &&
1055+
(pipe_cfg->dst_rect.x1 >= prev_pipe_cfg->dst_rect.x2 ||
1056+
prev_pipe_cfg->dst_rect.x1 >= pipe_cfg->dst_rect.x2)) {
1057+
pipe->sspp = prev_pipe->sspp;
1058+
1059+
pipe->multirect_index = DPU_SSPP_RECT_1;
1060+
pipe->multirect_mode = DPU_SSPP_MULTIRECT_PARALLEL;
1061+
1062+
prev_pipe->multirect_index = DPU_SSPP_RECT_0;
1063+
prev_pipe->multirect_mode = DPU_SSPP_MULTIRECT_PARALLEL;
1064+
1065+
return true;
1066+
}
1067+
1068+
if (pipe_cfg->dst_rect.y1 >= prev_pipe_cfg->dst_rect.y2 + 2 * max_tile_height ||
1069+
prev_pipe_cfg->dst_rect.y1 >= pipe_cfg->dst_rect.y2 + 2 * max_tile_height) {
1070+
pipe->sspp = prev_pipe->sspp;
1071+
1072+
pipe->multirect_index = DPU_SSPP_RECT_1;
1073+
pipe->multirect_mode = DPU_SSPP_MULTIRECT_TIME_MX;
1074+
1075+
prev_pipe->multirect_index = DPU_SSPP_RECT_0;
1076+
prev_pipe->multirect_mode = DPU_SSPP_MULTIRECT_TIME_MX;
1077+
1078+
return true;
1079+
}
1080+
1081+
return false;
1082+
}
1083+
10051084
static int dpu_plane_atomic_check(struct drm_plane *plane,
10061085
struct drm_atomic_state *state)
10071086
{
@@ -1102,13 +1181,14 @@ static int dpu_plane_virtual_atomic_check(struct drm_plane *plane,
11021181
static int dpu_plane_virtual_assign_resources(struct drm_crtc *crtc,
11031182
struct dpu_global_state *global_state,
11041183
struct drm_atomic_state *state,
1105-
struct drm_plane_state *plane_state)
1184+
struct drm_plane_state *plane_state,
1185+
struct drm_plane_state *prev_adjacent_plane_state)
11061186
{
11071187
const struct drm_crtc_state *crtc_state = NULL;
11081188
struct drm_plane *plane = plane_state->plane;
11091189
struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
11101190
struct dpu_rm_sspp_requirements reqs;
1111-
struct dpu_plane_state *pstate;
1191+
struct dpu_plane_state *pstate, *prev_adjacent_pstate;
11121192
struct dpu_sw_pipe *pipe;
11131193
struct dpu_sw_pipe *r_pipe;
11141194
struct dpu_sw_pipe_cfg *pipe_cfg;
@@ -1120,6 +1200,8 @@ static int dpu_plane_virtual_assign_resources(struct drm_crtc *crtc,
11201200
plane_state->crtc);
11211201

11221202
pstate = to_dpu_plane_state(plane_state);
1203+
prev_adjacent_pstate = prev_adjacent_plane_state ?
1204+
to_dpu_plane_state(prev_adjacent_plane_state) : NULL;
11231205
pipe = &pstate->pipe;
11241206
r_pipe = &pstate->r_pipe;
11251207
pipe_cfg = &pstate->pipe_cfg;
@@ -1138,24 +1220,42 @@ static int dpu_plane_virtual_assign_resources(struct drm_crtc *crtc,
11381220

11391221
reqs.rot90 = drm_rotation_90_or_270(plane_state->rotation);
11401222

1141-
pipe->sspp = dpu_rm_reserve_sspp(&dpu_kms->rm, global_state, crtc, &reqs);
1142-
if (!pipe->sspp)
1143-
return -ENODEV;
1223+
if (drm_rect_width(&r_pipe_cfg->src_rect) == 0) {
1224+
if (!prev_adjacent_pstate ||
1225+
!dpu_plane_try_multirect_shared(pstate, prev_adjacent_pstate, fmt,
1226+
dpu_kms->catalog->caps->max_linewidth)) {
1227+
pipe->sspp = dpu_rm_reserve_sspp(&dpu_kms->rm, global_state, crtc, &reqs);
1228+
if (!pipe->sspp)
1229+
return -ENODEV;
11441230

1145-
if (!dpu_plane_try_multirect_parallel(pipe, pipe_cfg, r_pipe, r_pipe_cfg,
1146-
pipe->sspp,
1147-
msm_framebuffer_format(plane_state->fb),
1148-
dpu_kms->catalog->caps->max_linewidth)) {
1149-
/* multirect is not possible, use two SSPP blocks */
1150-
r_pipe->sspp = dpu_rm_reserve_sspp(&dpu_kms->rm, global_state, crtc, &reqs);
1151-
if (!r_pipe->sspp)
1231+
r_pipe->sspp = NULL;
1232+
1233+
pipe->multirect_index = DPU_SSPP_RECT_SOLO;
1234+
pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE;
1235+
1236+
r_pipe->multirect_index = DPU_SSPP_RECT_SOLO;
1237+
r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE;
1238+
}
1239+
} else {
1240+
pipe->sspp = dpu_rm_reserve_sspp(&dpu_kms->rm, global_state, crtc, &reqs);
1241+
if (!pipe->sspp)
11521242
return -ENODEV;
11531243

1154-
pipe->multirect_index = DPU_SSPP_RECT_SOLO;
1155-
pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE;
1244+
if (!dpu_plane_try_multirect_parallel(pipe, pipe_cfg, r_pipe, r_pipe_cfg,
1245+
pipe->sspp,
1246+
msm_framebuffer_format(plane_state->fb),
1247+
dpu_kms->catalog->caps->max_linewidth)) {
1248+
/* multirect is not possible, use two SSPP blocks */
1249+
r_pipe->sspp = dpu_rm_reserve_sspp(&dpu_kms->rm, global_state, crtc, &reqs);
1250+
if (!r_pipe->sspp)
1251+
return -ENODEV;
11561252

1157-
r_pipe->multirect_index = DPU_SSPP_RECT_SOLO;
1158-
r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE;
1253+
pipe->multirect_index = DPU_SSPP_RECT_SOLO;
1254+
pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE;
1255+
1256+
r_pipe->multirect_index = DPU_SSPP_RECT_SOLO;
1257+
r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE;
1258+
}
11591259
}
11601260

11611261
return dpu_plane_atomic_check_sspp(plane, state, crtc_state);
@@ -1168,6 +1268,7 @@ int dpu_assign_plane_resources(struct dpu_global_state *global_state,
11681268
unsigned int num_planes)
11691269
{
11701270
unsigned int i;
1271+
struct drm_plane_state *prev_adjacent_plane_state = NULL;
11711272

11721273
for (i = 0; i < num_planes; i++) {
11731274
struct drm_plane_state *plane_state = states[i];
@@ -1177,9 +1278,12 @@ int dpu_assign_plane_resources(struct dpu_global_state *global_state,
11771278
continue;
11781279

11791280
int ret = dpu_plane_virtual_assign_resources(crtc, global_state,
1180-
state, plane_state);
1281+
state, plane_state,
1282+
prev_adjacent_plane_state);
11811283
if (ret)
1182-
return ret;
1284+
break;
1285+
1286+
prev_adjacent_plane_state = plane_state;
11831287
}
11841288

11851289
return 0;

0 commit comments

Comments
 (0)