Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/msm/dpu: Enable quad-pipe for DSC and dual-DSI case

To support high-resolution cases that exceed the width limitation of
a pair of SSPPs, or scenarios that surpass the maximum MDP clock rate,
additional pipes are necessary to enable parallel data processing
within the SSPP width constraints and MDP clock rate.

Request 4 mixers and 4 DSCs for high-resolution cases where both DSC
and dual interfaces are enabled. More use cases can be incorporated
later if quad-pipe capabilities are required.

Signed-off-by: Jun Nie <jun.nie@linaro.org>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Reviewed-by: Jessica Zhang <quic_jesszhan@quicinc.com>
Patchwork: https://patchwork.freedesktop.org/patch/675418/
Link: https://lore.kernel.org/r/20250918-v6-16-rc2-quad-pipe-upstream-4-v16-10-ff6232e3472f@linaro.org
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>

authored by

Jun Nie and committed by
Dmitry Baryshkov
d7ec9366 5978864e

+35 -33
+20 -7
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
··· 200 200 struct dpu_crtc_state *crtc_state) 201 201 { 202 202 struct dpu_crtc_mixer *m; 203 - u32 crcs[CRTC_DUAL_MIXERS]; 203 + u32 crcs[CRTC_QUAD_MIXERS]; 204 204 205 205 int rc = 0; 206 206 int i; ··· 1328 1328 struct drm_display_mode *mode = &crtc_state->adjusted_mode; 1329 1329 struct msm_display_topology topology = {0}; 1330 1330 struct drm_encoder *drm_enc; 1331 + u32 num_rt_intf; 1331 1332 1332 1333 drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask) 1333 1334 dpu_encoder_update_topology(drm_enc, &topology, crtc_state->state, ··· 1342 1341 * Dual display 1343 1342 * 2 LM, 2 INTF ( Split display using 2 interfaces) 1344 1343 * 1344 + * If DSC is enabled, try to use 4:4:2 topology if there is enough 1345 + * resource. Otherwise, use 2:2:2 topology. 1346 + * 1345 1347 * Single display 1346 1348 * 1 LM, 1 INTF 1347 1349 * 2 LM, 1 INTF (stream merge to support high resolution interfaces) 1348 1350 * 1349 - * If DSC is enabled, use 2 LMs for 2:2:1 topology 1351 + * If DSC is enabled, use 2:2:1 topology 1350 1352 * 1351 1353 * Add dspps to the reservation requirements if ctm is requested 1352 1354 * ··· 1361 1357 * (mode->hdisplay > MAX_HDISPLAY_SPLIT) check. 1362 1358 */ 1363 1359 1364 - if (topology.num_intf == 2 && !topology.cwb_enabled) 1360 + num_rt_intf = topology.num_intf; 1361 + if (topology.cwb_enabled) 1362 + num_rt_intf--; 1363 + 1364 + if (topology.num_dsc) { 1365 + if (dpu_kms->catalog->dsc_count >= num_rt_intf * 2) 1366 + topology.num_dsc = num_rt_intf * 2; 1367 + else 1368 + topology.num_dsc = num_rt_intf; 1369 + topology.num_lm = topology.num_dsc; 1370 + } else if (num_rt_intf == 2) { 1365 1371 topology.num_lm = 2; 1366 - else if (topology.num_dsc == 2) 1367 - topology.num_lm = 2; 1368 - else if (dpu_kms->catalog->caps->has_3d_merge) 1372 + } else if (dpu_kms->catalog->caps->has_3d_merge) { 1369 1373 topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1; 1370 - else 1374 + } else { 1371 1375 topology.num_lm = 1; 1376 + } 1372 1377 1373 1378 if (crtc_state->ctm) 1374 1379 topology.num_dspp = topology.num_lm;
+3 -3
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
··· 210 210 211 211 bool bw_control; 212 212 bool bw_split_vote; 213 - struct drm_rect lm_bounds[CRTC_DUAL_MIXERS]; 213 + struct drm_rect lm_bounds[CRTC_QUAD_MIXERS]; 214 214 215 215 uint64_t input_fence_timeout_ns; 216 216 ··· 218 218 219 219 /* HW Resources reserved for the crtc */ 220 220 u32 num_mixers; 221 - struct dpu_crtc_mixer mixers[CRTC_DUAL_MIXERS]; 221 + struct dpu_crtc_mixer mixers[CRTC_QUAD_MIXERS]; 222 222 223 223 u32 num_ctls; 224 - struct dpu_hw_ctl *hw_ctls[CRTC_DUAL_MIXERS]; 224 + struct dpu_hw_ctl *hw_ctls[CRTC_QUAD_MIXERS]; 225 225 226 226 enum dpu_crtc_crc_source crc_source; 227 227 int crc_frame_skip_count;
+9 -20
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
··· 55 55 #define MAX_PHYS_ENCODERS_PER_VIRTUAL \ 56 56 (MAX_H_TILES_PER_DISPLAY * NUM_PHYS_ENCODER_TYPES) 57 57 58 - #define MAX_CHANNELS_PER_ENC 2 58 + #define MAX_CHANNELS_PER_ENC 4 59 59 #define MAX_CWB_PER_ENC 2 60 60 61 61 #define IDLE_SHORT_TIMEOUT 1 ··· 661 661 struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc); 662 662 struct msm_drm_private *priv = dpu_enc->base.dev->dev_private; 663 663 struct msm_display_info *disp_info = &dpu_enc->disp_info; 664 - struct dpu_kms *dpu_kms = to_dpu_kms(priv->kms); 665 664 struct drm_connector *connector; 666 665 struct drm_connector_state *conn_state; 667 666 struct drm_framebuffer *fb; ··· 674 675 675 676 dsc = dpu_encoder_get_dsc_config(drm_enc); 676 677 677 - /* We only support 2 DSC mode (with 2 LM and 1 INTF) */ 678 - if (dsc) { 679 - /* 680 - * Use 2 DSC encoders, 2 layer mixers and 1 or 2 interfaces 681 - * when Display Stream Compression (DSC) is enabled, 682 - * and when enough DSC blocks are available. 683 - * This is power-optimal and can drive up to (including) 4k 684 - * screens. 685 - */ 686 - WARN(topology->num_intf > 2, 687 - "DSC topology cannot support more than 2 interfaces\n"); 688 - if (topology->num_intf >= 2 || dpu_kms->catalog->dsc_count >= 2) 689 - topology->num_dsc = 2; 690 - else 691 - topology->num_dsc = 1; 692 - } 678 + /* 679 + * Set DSC number as 1 to mark the enabled status, will be adjusted 680 + * in dpu_crtc_get_topology() 681 + */ 682 + if (dsc) 683 + topology->num_dsc = 1; 693 684 694 685 connector = drm_atomic_get_new_connector_for_encoder(state, drm_enc); 695 686 if (!connector) ··· 2169 2180 { 2170 2181 int i, num_lm; 2171 2182 struct dpu_global_state *global_state; 2172 - struct dpu_hw_blk *hw_lm[2]; 2173 - struct dpu_hw_mixer *hw_mixer[2]; 2183 + struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC]; 2184 + struct dpu_hw_mixer *hw_mixer[MAX_CHANNELS_PER_ENC]; 2174 2185 struct dpu_hw_ctl *ctl = phys_enc->hw_ctl; 2175 2186 2176 2187 /* reset all mixers for this encoder */
+1 -1
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
··· 302 302 303 303 /* Use merge_3d unless DSC MERGE topology is used */ 304 304 if (phys_enc->split_role == ENC_ROLE_SOLO && 305 - dpu_cstate->num_mixers == CRTC_DUAL_MIXERS && 305 + (dpu_cstate->num_mixers != 1) && 306 306 !dpu_encoder_use_dsc_merge(phys_enc->parent)) 307 307 return BLEND_3D_H_ROW_INT; 308 308
+1 -1
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
··· 24 24 #define DPU_MAX_IMG_WIDTH 0x3fff 25 25 #define DPU_MAX_IMG_HEIGHT 0x3fff 26 26 27 - #define CRTC_DUAL_MIXERS 2 27 + #define CRTC_QUAD_MIXERS 4 28 28 29 29 #define MAX_XIN_COUNT 16 30 30
+1 -1
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
··· 34 34 #define DPU_MAX_PLANES 4 35 35 #endif 36 36 37 - #define STAGES_PER_PLANE 1 37 + #define STAGES_PER_PLANE 2 38 38 #define PIPES_PER_STAGE 2 39 39 #define PIPES_PER_PLANE (PIPES_PER_STAGE * STAGES_PER_PLANE) 40 40 #ifndef DPU_MAX_DE_CURVES