[PATCH v4 1/6] drm/msm/dpu: split modes a single layer mixer cannot clock
From: Mahadevan P
Date: Thu Oct 08 2026 - 13:29:23 EST
The layer mixer count is picked purely from the mode width, via the
MAX_HDISPLAY_SPLIT threshold. Width is only half of what constrains a
mixer: it also processes one pixel per core clock cycle, so a mode narrow
enough to stay under the width threshold can still demand a higher pixel
rate than one mixer sustains. A 1080 wide panel at a few hundred Hz is
enough to get there.
Such a mode is currently given a single mixer and then has to be clocked
past the maximum core clock rate, which that mixer cannot do.
Factor the decision out into dpu_crtc_num_lm_for_mode() and have it ask
for a second mixer when the adjusted mode clock does not fit the maximum
core clock rate, in addition to the existing width test. Modes that
already fit within one mixer are unaffected, so the only decisions that
change are the ones that could not be driven as they were.
Assisted-by: LLM
Signed-off-by: Mahadevan P <mahadevan.p@xxxxxxxxxxxxxxxx>
---
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 25 ++++++++++++++++++++++---
1 file changed, 22 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 77a2d1f6700d..0b51a4c5db57 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -1376,6 +1376,25 @@ static int dpu_crtc_reassign_planes(struct drm_crtc *crtc, struct drm_crtc_state
#define MAX_CHANNELS_PER_CRTC PIPES_PER_PLANE
#define MAX_HDISPLAY_SPLIT 1080
+static u32 dpu_crtc_num_lm_for_mode(struct dpu_kms *dpu_kms,
+ const struct drm_display_mode *mode)
+{
+ u64 mode_clk;
+
+ if (!dpu_kms->catalog->caps->has_3d_merge)
+ return 1;
+
+ if (mode->hdisplay > MAX_HDISPLAY_SPLIT)
+ return 2;
+
+ mode_clk = dpu_core_perf_adjusted_mode_clk(mode->clock,
+ dpu_kms->perf.perf_cfg);
+ if (mode_clk * 1000 > dpu_kms->perf.max_core_clk_rate)
+ return 2;
+
+ return 1;
+}
+
static struct msm_display_topology dpu_crtc_get_topology(
struct drm_crtc *crtc,
struct dpu_kms *dpu_kms,
@@ -1409,8 +1428,8 @@ static struct msm_display_topology dpu_crtc_get_topology(
* enabled. This is because in cases where CWB is enabled, num_intf will
* count both the WB and real-time phys encoders.
*
- * For non-DSC CWB usecases, have the num_lm be decided by the
- * (mode->hdisplay > MAX_HDISPLAY_SPLIT) check.
+ * For non-DSC CWB usecases, have the num_lm be decided by
+ * dpu_crtc_num_lm_for_mode().
*/
if (topology.num_intf == 2 && !topology.cwb_enabled)
@@ -1419,7 +1438,7 @@ static struct msm_display_topology dpu_crtc_get_topology(
topology.num_lm = 2;
else if (dpu_kms->catalog->caps->has_3d_merge &&
topology.num_dsc == 0)
- topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1;
+ topology.num_lm = dpu_crtc_num_lm_for_mode(dpu_kms, mode);
else
topology.num_lm = 1;
--
2.34.1