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

Configure Feed

Select the types of activity you want to include in your feed.

drm/msm/dpu: move resource allocation to CRTC

All resource allocation is centered around the LMs. Then other blocks
(except DSCs) are allocated basing on the LMs that was selected, and LM
powers up the CRTC rather than the encoder.

Moreover if at some point the driver supports encoder cloning,
allocating resources from the encoder will be incorrect, as all clones
will have different encoder IDs, while LMs are to be shared by these
encoders.

In addition, move mode_changed() to dpu_crtc as encoder no longer has
access to topology information

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
[quic_abhinavk@quicinc.com: Refactored resource allocation for CDM]
Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
[quic_jesszhan@quicinc.com: Changed to grabbing exising global state]
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
[DB: rebased on top of msm-next]
[DB: fixed resource allcoation to ignore the active_changed flag]
Patchwork: https://patchwork.freedesktop.org/patch/637487/
Link: https://lore.kernel.org/r/20250214-concurrent-wb-v6-2-a44c293cf422@quicinc.com
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>

+145 -134
+81 -1
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
··· 1231 1231 } 1232 1232 1233 1233 #define MAX_CHANNELS_PER_CRTC 2 1234 + #define MAX_HDISPLAY_SPLIT 1080 1235 + 1236 + static struct msm_display_topology dpu_crtc_get_topology( 1237 + struct drm_crtc *crtc, 1238 + struct dpu_kms *dpu_kms, 1239 + struct drm_crtc_state *crtc_state) 1240 + { 1241 + struct drm_display_mode *mode = &crtc_state->adjusted_mode; 1242 + struct msm_display_topology topology = {0}; 1243 + struct drm_encoder *drm_enc; 1244 + 1245 + drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask) 1246 + dpu_encoder_update_topology(drm_enc, &topology, crtc_state->state, 1247 + &crtc_state->adjusted_mode); 1248 + 1249 + /* 1250 + * Datapath topology selection 1251 + * 1252 + * Dual display 1253 + * 2 LM, 2 INTF ( Split display using 2 interfaces) 1254 + * 1255 + * Single display 1256 + * 1 LM, 1 INTF 1257 + * 2 LM, 1 INTF (stream merge to support high resolution interfaces) 1258 + * 1259 + * If DSC is enabled, use 2 LMs for 2:2:1 topology 1260 + * 1261 + * Add dspps to the reservation requirements if ctm is requested 1262 + */ 1263 + 1264 + if (topology.num_intf == 2) 1265 + topology.num_lm = 2; 1266 + else if (topology.num_dsc == 2) 1267 + topology.num_lm = 2; 1268 + else if (dpu_kms->catalog->caps->has_3d_merge) 1269 + topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1; 1270 + else 1271 + topology.num_lm = 1; 1272 + 1273 + if (crtc_state->ctm) 1274 + topology.num_dspp = topology.num_lm; 1275 + 1276 + return topology; 1277 + } 1234 1278 1235 1279 static int dpu_crtc_assign_resources(struct drm_crtc *crtc, 1236 1280 struct drm_crtc_state *crtc_state) ··· 1287 1243 struct dpu_global_state *global_state; 1288 1244 struct dpu_crtc_state *cstate; 1289 1245 struct drm_encoder *drm_enc; 1246 + struct msm_display_topology topology; 1247 + int ret; 1290 1248 1291 1249 /* 1292 1250 * For now, grab the first encoder in the crtc state as we don't ··· 1297 1251 drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask) 1298 1252 break; 1299 1253 1254 + /* 1255 + * Release and Allocate resources on every modeset 1256 + */ 1300 1257 global_state = dpu_kms_get_global_state(crtc_state->state); 1301 1258 if (IS_ERR(global_state)) 1302 1259 return PTR_ERR(global_state); 1303 1260 1261 + dpu_rm_release(global_state, drm_enc); 1262 + 1304 1263 if (!crtc_state->enable) 1305 1264 return 0; 1265 + 1266 + topology = dpu_crtc_get_topology(crtc, dpu_kms, crtc_state); 1267 + ret = dpu_rm_reserve(&dpu_kms->rm, global_state, 1268 + drm_enc, crtc_state, &topology); 1269 + if (ret) 1270 + return ret; 1306 1271 1307 1272 cstate = to_dpu_crtc_state(crtc_state); 1308 1273 ··· 1344 1287 return 0; 1345 1288 } 1346 1289 1290 + /** 1291 + * dpu_crtc_check_mode_changed: check if full modeset is required 1292 + * @crtc_state: Corresponding CRTC state to be checked 1293 + * 1294 + * Check if the changes in the object properties demand full mode set. 1295 + */ 1296 + int dpu_crtc_check_mode_changed(struct drm_crtc_state *crtc_state) 1297 + { 1298 + struct drm_encoder *drm_enc; 1299 + struct drm_crtc *crtc = crtc_state->crtc; 1300 + 1301 + DRM_DEBUG_ATOMIC("%d\n", crtc->base.id); 1302 + 1303 + /* there might be cases where encoder needs a modeset too */ 1304 + drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask) { 1305 + if (dpu_encoder_needs_modeset(drm_enc, crtc_state->state)) 1306 + crtc_state->mode_changed = true; 1307 + } 1308 + 1309 + return 0; 1310 + } 1311 + 1347 1312 static int dpu_crtc_atomic_check(struct drm_crtc *crtc, 1348 1313 struct drm_atomic_state *state) 1349 1314 { ··· 1381 1302 1382 1303 bool needs_dirtyfb = dpu_crtc_needs_dirtyfb(crtc_state); 1383 1304 1384 - if (drm_atomic_crtc_needs_modeset(crtc_state)) { 1305 + /* don't reallocate resources if only ACTIVE has beeen changed */ 1306 + if (crtc_state->mode_changed || crtc_state->connectors_changed) { 1385 1307 rc = dpu_crtc_assign_resources(crtc, crtc_state); 1386 1308 if (rc < 0) 1387 1309 return rc;
+2
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
··· 239 239 return crtc ? atomic_read(&to_dpu_crtc(crtc)->frame_pending) : -EINVAL; 240 240 } 241 241 242 + int dpu_crtc_check_mode_changed(struct drm_crtc_state *crtc_state); 243 + 242 244 int dpu_crtc_vblank(struct drm_crtc *crtc, bool en); 243 245 244 246 void dpu_crtc_vblank_callback(struct drm_crtc *crtc);
+52 -115
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
··· 58 58 59 59 #define IDLE_SHORT_TIMEOUT 1 60 60 61 - #define MAX_HDISPLAY_SPLIT 1080 62 - 63 61 /* timeout in frames waiting for frame done */ 64 62 #define DPU_ENCODER_FRAME_DONE_TIMEOUT_FRAMES 5 65 63 ··· 645 647 return NULL; 646 648 } 647 649 648 - static struct msm_display_topology dpu_encoder_get_topology( 649 - struct dpu_encoder_virt *dpu_enc, 650 - struct drm_display_mode *mode, 651 - struct drm_crtc_state *crtc_state, 652 - struct drm_connector_state *conn_state) 650 + void dpu_encoder_update_topology(struct drm_encoder *drm_enc, 651 + struct msm_display_topology *topology, 652 + struct drm_atomic_state *state, 653 + const struct drm_display_mode *adj_mode) 653 654 { 655 + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc); 654 656 struct msm_drm_private *priv = dpu_enc->base.dev->dev_private; 655 657 struct msm_display_info *disp_info = &dpu_enc->disp_info; 656 658 struct dpu_kms *dpu_kms = to_dpu_kms(priv->kms); 657 - struct drm_dsc_config *dsc = dpu_encoder_get_dsc_config(&dpu_enc->base); 658 - struct msm_display_topology topology = {0}; 659 - int i, intf_count = 0; 659 + struct drm_connector *connector; 660 + struct drm_connector_state *conn_state; 661 + struct drm_framebuffer *fb; 662 + struct drm_dsc_config *dsc; 663 + 664 + int i; 660 665 661 666 for (i = 0; i < MAX_PHYS_ENCODERS_PER_VIRTUAL; i++) 662 667 if (dpu_enc->phys_encs[i]) 663 - intf_count++; 668 + topology->num_intf++; 664 669 665 - /* Datapath topology selection 666 - * 667 - * Dual display 668 - * 2 LM, 2 INTF ( Split display using 2 interfaces) 669 - * 670 - * Single display 671 - * 1 LM, 1 INTF 672 - * 2 LM, 1 INTF (stream merge to support high resolution interfaces) 673 - * 674 - * Add dspps to the reservation requirements if ctm is requested 675 - */ 676 - if (intf_count == 2) 677 - topology.num_lm = 2; 678 - else if (!dpu_kms->catalog->caps->has_3d_merge) 679 - topology.num_lm = 1; 680 - else 681 - topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1; 670 + dsc = dpu_encoder_get_dsc_config(drm_enc); 682 671 683 - if (crtc_state->ctm) 684 - topology.num_dspp = topology.num_lm; 685 - 686 - topology.num_intf = intf_count; 687 - 672 + /* We only support 2 DSC mode (with 2 LM and 1 INTF) */ 688 673 if (dsc) { 689 674 /* 690 675 * Use 2 DSC encoders, 2 layer mixers and 1 or 2 interfaces ··· 676 695 * This is power-optimal and can drive up to (including) 4k 677 696 * screens. 678 697 */ 679 - WARN(topology.num_intf > 2, 698 + WARN(topology->num_intf > 2, 680 699 "DSC topology cannot support more than 2 interfaces\n"); 681 - if (intf_count >= 2 || dpu_kms->catalog->dsc_count >= 2) { 682 - topology.num_dsc = 2; 683 - topology.num_lm = 2; 684 - } else { 685 - topology.num_dsc = 1; 686 - topology.num_lm = 1; 687 - } 700 + if (topology->num_intf >= 2 || dpu_kms->catalog->dsc_count >= 2) 701 + topology->num_dsc = 2; 702 + else 703 + topology->num_dsc = 1; 688 704 } 705 + 706 + connector = drm_atomic_get_new_connector_for_encoder(state, drm_enc); 707 + if (!connector) 708 + return; 709 + conn_state = drm_atomic_get_new_connector_state(state, connector); 710 + if (!conn_state) 711 + return; 689 712 690 713 /* 691 714 * Use CDM only for writeback or DP at the moment as other interfaces cannot handle it. ··· 697 712 * earlier. 698 713 */ 699 714 if (disp_info->intf_type == INTF_WB && conn_state->writeback_job) { 700 - struct drm_framebuffer *fb; 701 - 702 715 fb = conn_state->writeback_job->fb; 703 716 704 717 if (fb && MSM_FORMAT_IS_YUV(msm_framebuffer_format(fb))) 705 - topology.needs_cdm = true; 718 + topology->needs_cdm = true; 706 719 } else if (disp_info->intf_type == INTF_DP) { 707 - if (msm_dp_is_yuv_420_enabled(priv->dp[disp_info->h_tile_instance[0]], mode)) 708 - topology.needs_cdm = true; 720 + if (msm_dp_is_yuv_420_enabled(priv->dp[disp_info->h_tile_instance[0]], adj_mode)) 721 + topology->needs_cdm = true; 709 722 } 710 - 711 - return topology; 712 723 } 713 724 714 - /** 715 - * dpu_encoder_virt_check_mode_changed: check if full modeset is required 716 - * @drm_enc: Pointer to drm encoder structure 717 - * @crtc_state: Corresponding CRTC state to be checked 718 - * @conn_state: Corresponding Connector's state to be checked 719 - * 720 - * Check if the changes in the object properties demand full mode set. 721 - */ 722 - int dpu_encoder_virt_check_mode_changed(struct drm_encoder *drm_enc, 723 - struct drm_crtc_state *crtc_state, 724 - struct drm_connector_state *conn_state) 725 + bool dpu_encoder_needs_modeset(struct drm_encoder *drm_enc, struct drm_atomic_state *state) 725 726 { 727 + struct drm_connector *connector; 728 + struct drm_connector_state *conn_state; 729 + struct drm_framebuffer *fb; 726 730 struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc); 727 - struct msm_display_topology topology; 728 731 729 - DPU_DEBUG_ENC(dpu_enc, "\n"); 732 + if (!drm_enc || !state) 733 + return false; 730 734 731 - /* Using mode instead of adjusted_mode as it wasn't computed yet */ 732 - topology = dpu_encoder_get_topology(dpu_enc, &crtc_state->mode, crtc_state, conn_state); 735 + connector = drm_atomic_get_new_connector_for_encoder(state, drm_enc); 736 + if (!connector) 737 + return false; 733 738 734 - if (topology.needs_cdm && !dpu_enc->cur_master->hw_cdm) 735 - crtc_state->mode_changed = true; 736 - else if (!topology.needs_cdm && dpu_enc->cur_master->hw_cdm) 737 - crtc_state->mode_changed = true; 739 + conn_state = drm_atomic_get_new_connector_state(state, connector); 738 740 739 - return 0; 740 - } 741 - 742 - static int dpu_encoder_virt_atomic_check( 743 - struct drm_encoder *drm_enc, 744 - struct drm_crtc_state *crtc_state, 745 - struct drm_connector_state *conn_state) 746 - { 747 - struct dpu_encoder_virt *dpu_enc; 748 - struct msm_drm_private *priv; 749 - struct dpu_kms *dpu_kms; 750 - struct drm_display_mode *adj_mode; 751 - struct msm_display_topology topology; 752 - struct dpu_global_state *global_state; 753 - int ret = 0; 754 - 755 - if (!drm_enc || !crtc_state || !conn_state) { 756 - DPU_ERROR("invalid arg(s), drm_enc %d, crtc/conn state %d/%d\n", 757 - drm_enc != NULL, crtc_state != NULL, conn_state != NULL); 758 - return -EINVAL; 759 - } 760 - 761 - dpu_enc = to_dpu_encoder_virt(drm_enc); 762 - DPU_DEBUG_ENC(dpu_enc, "\n"); 763 - 764 - priv = drm_enc->dev->dev_private; 765 - dpu_kms = to_dpu_kms(priv->kms); 766 - adj_mode = &crtc_state->adjusted_mode; 767 - global_state = dpu_kms_get_global_state(crtc_state->state); 768 - if (IS_ERR(global_state)) 769 - return PTR_ERR(global_state); 770 - 771 - trace_dpu_enc_atomic_check(DRMID(drm_enc)); 772 - 773 - topology = dpu_encoder_get_topology(dpu_enc, adj_mode, crtc_state, conn_state); 774 - 775 - /* 776 - * Release and Allocate resources on every modeset 741 + /** 742 + * These checks are duplicated from dpu_encoder_update_topology() since 743 + * CRTC and encoder don't hold topology information 777 744 */ 778 - if (drm_atomic_crtc_needs_modeset(crtc_state)) { 779 - dpu_rm_release(global_state, drm_enc); 780 - 781 - if (crtc_state->enable) 782 - ret = dpu_rm_reserve(&dpu_kms->rm, global_state, 783 - drm_enc, crtc_state, &topology); 745 + if (dpu_enc->disp_info.intf_type == INTF_WB && conn_state->writeback_job) { 746 + fb = conn_state->writeback_job->fb; 747 + if (fb && MSM_FORMAT_IS_YUV(msm_framebuffer_format(fb))) { 748 + if (!dpu_enc->cur_master->hw_cdm) 749 + return true; 750 + } else { 751 + if (dpu_enc->cur_master->hw_cdm) 752 + return true; 753 + } 784 754 } 785 755 786 - trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags); 787 - 788 - return ret; 756 + return false; 789 757 } 790 758 791 759 static void _dpu_encoder_update_vsync_source(struct dpu_encoder_virt *dpu_enc, ··· 2557 2619 .atomic_mode_set = dpu_encoder_virt_atomic_mode_set, 2558 2620 .atomic_disable = dpu_encoder_virt_atomic_disable, 2559 2621 .atomic_enable = dpu_encoder_virt_atomic_enable, 2560 - .atomic_check = dpu_encoder_virt_atomic_check, 2561 2622 }; 2562 2623 2563 2624 static const struct drm_encoder_funcs dpu_encoder_funcs = {
+7 -4
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
··· 80 80 81 81 bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc); 82 82 83 + void dpu_encoder_update_topology(struct drm_encoder *drm_enc, 84 + struct msm_display_topology *topology, 85 + struct drm_atomic_state *state, 86 + const struct drm_display_mode *adj_mode); 87 + 88 + bool dpu_encoder_needs_modeset(struct drm_encoder *drm_enc, struct drm_atomic_state *state); 89 + 83 90 void dpu_encoder_prepare_wb_job(struct drm_encoder *drm_enc, 84 91 struct drm_writeback_job *job); 85 92 ··· 94 87 struct drm_writeback_job *job); 95 88 96 89 bool dpu_encoder_is_valid_for_commit(struct drm_encoder *drm_enc); 97 - 98 - int dpu_encoder_virt_check_mode_changed(struct drm_encoder *drm_enc, 99 - struct drm_crtc_state *crtc_state, 100 - struct drm_connector_state *conn_state); 101 90 102 91 #endif /* __DPU_ENCODER_H__ */
+3 -14
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
··· 449 449 static int dpu_kms_check_mode_changed(struct msm_kms *kms, struct drm_atomic_state *state) 450 450 { 451 451 struct drm_crtc_state *new_crtc_state; 452 - struct drm_connector *connector; 453 - struct drm_connector_state *new_conn_state; 452 + struct drm_crtc *crtc; 454 453 int i; 455 454 456 - for_each_new_connector_in_state(state, connector, new_conn_state, i) { 457 - struct drm_encoder *encoder; 458 - 459 - if (!new_conn_state->crtc || !new_conn_state->best_encoder) 460 - continue; 461 - 462 - new_crtc_state = drm_atomic_get_new_crtc_state(state, new_conn_state->crtc); 463 - 464 - encoder = new_conn_state->best_encoder; 465 - 466 - dpu_encoder_virt_check_mode_changed(encoder, new_crtc_state, new_conn_state); 467 - } 455 + for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) 456 + dpu_crtc_check_mode_changed(new_crtc_state); 468 457 469 458 return 0; 470 459 }