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

drm/msm/dpu: add support for color processing blocks in dpu driver

This change adds support to configure dspp blocks in
the dpu driver.

Macro description of the changes coming in this patch.
1) Add dspp definitions in the hw catalog.
2) Add capability to reserve dspp blocks in the display data path.
3) Attach the reserved block to the encoder.

Signed-off-by: Kalyan Thota <kalyan_t@codeaurora.org>
Tested-by: Fritz Koenig <frkoenig@google.com>
Signed-off-by: Rob Clark <robdclark@chromium.org>

authored by

Kalyan Thota and committed by
Rob Clark
e47616df e4337877

+322 -15
+1
drivers/gpu/drm/msm/Makefile
··· 65 65 disp/dpu1/dpu_hw_lm.o \ 66 66 disp/dpu1/dpu_hw_pingpong.o \ 67 67 disp/dpu1/dpu_hw_sspp.o \ 68 + disp/dpu1/dpu_hw_dspp.o \ 68 69 disp/dpu1/dpu_hw_top.o \ 69 70 disp/dpu1/dpu_hw_util.o \ 70 71 disp/dpu1/dpu_hw_vbif.o \
+2
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
··· 73 73 * struct dpu_crtc_mixer: stores the map for each virtual pipeline in the CRTC 74 74 * @hw_lm: LM HW Driver context 75 75 * @lm_ctl: CTL Path HW driver context 76 + * @lm_dspp: DSPP HW driver context 76 77 * @mixer_op_mode: mixer blending operation mode 77 78 * @flush_mask: mixer flush mask for ctl, mixer and pipe 78 79 */ 79 80 struct dpu_crtc_mixer { 80 81 struct dpu_hw_mixer *hw_lm; 81 82 struct dpu_hw_ctl *lm_ctl; 83 + struct dpu_hw_dspp *hw_dspp; 82 84 u32 mixer_op_mode; 83 85 u32 flush_mask; 84 86 };
+11 -1
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
··· 20 20 #include "dpu_hw_catalog.h" 21 21 #include "dpu_hw_intf.h" 22 22 #include "dpu_hw_ctl.h" 23 + #include "dpu_hw_dspp.h" 23 24 #include "dpu_formats.h" 24 25 #include "dpu_encoder_phys.h" 25 26 #include "dpu_crtc.h" ··· 537 536 * 1 LM, 1 INTF 538 537 * 2 LM, 1 INTF (stream merge to support high resolution interfaces) 539 538 * 539 + * Adding color blocks only to primary interface 540 540 */ 541 541 if (intf_count == 2) 542 542 topology.num_lm = 2; ··· 545 543 topology.num_lm = 1; 546 544 else 547 545 topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1; 546 + 547 + if (dpu_enc->disp_info.intf_type == DRM_MODE_ENCODER_DSI) 548 + topology.num_dspp = topology.num_lm; 548 549 549 550 topology.num_enc = 0; 550 551 topology.num_intf = intf_count; ··· 964 959 struct dpu_hw_blk *hw_pp[MAX_CHANNELS_PER_ENC]; 965 960 struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC]; 966 961 struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC]; 967 - int num_lm, num_ctl, num_pp; 962 + struct dpu_hw_blk *hw_dspp[MAX_CHANNELS_PER_ENC] = { NULL }; 963 + int num_lm, num_ctl, num_pp, num_dspp; 968 964 int i, j; 969 965 970 966 if (!drm_enc) { ··· 1014 1008 drm_enc->base.id, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl)); 1015 1009 num_lm = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, 1016 1010 drm_enc->base.id, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm)); 1011 + num_dspp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, 1012 + drm_enc->base.id, DPU_HW_BLK_DSPP, hw_dspp, 1013 + ARRAY_SIZE(hw_dspp)); 1017 1014 1018 1015 for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) 1019 1016 dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i]) ··· 1029 1020 1030 1021 cstate->mixers[i].hw_lm = to_dpu_hw_mixer(hw_lm[i]); 1031 1022 cstate->mixers[i].lm_ctl = to_dpu_hw_ctl(hw_ctl[ctl_idx]); 1023 + cstate->mixers[i].hw_dspp = to_dpu_hw_dspp(hw_dspp[i]); 1032 1024 } 1033 1025 1034 1026 cstate->num_mixers = num_lm;
+29 -10
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
··· 41 41 #define PINGPONG_SDM845_SPLIT_MASK \ 42 42 (PINGPONG_SDM845_MASK | BIT(DPU_PINGPONG_TE2)) 43 43 44 + #define DSPP_SC7180_MASK 0 45 + 44 46 #define DEFAULT_PIXEL_RAM_SIZE (50 * 1024) 45 47 #define DEFAULT_DPU_LINE_WIDTH 2048 46 48 #define DEFAULT_DPU_OUTPUT_LINE_WIDTH 2560 ··· 293 291 }, 294 292 }; 295 293 296 - #define LM_BLK(_name, _id, _base, _fmask, _sblk, _pp, _lmpair) \ 294 + #define LM_BLK(_name, _id, _base, _fmask, _sblk, _pp, _lmpair, _dspp) \ 297 295 { \ 298 296 .name = _name, .id = _id, \ 299 297 .base = _base, .len = 0x320, \ 300 298 .features = _fmask, \ 301 299 .sblk = _sblk, \ 302 300 .pingpong = _pp, \ 303 - .lm_pair_mask = (1 << _lmpair) \ 301 + .lm_pair_mask = (1 << _lmpair), \ 302 + .dspp = _dspp \ 304 303 } 305 304 306 305 static const struct dpu_lm_cfg sdm845_lm[] = { 307 306 LM_BLK("lm_0", LM_0, 0x44000, MIXER_SDM845_MASK, 308 - &sdm845_lm_sblk, PINGPONG_0, LM_1), 307 + &sdm845_lm_sblk, PINGPONG_0, LM_1, 0), 309 308 LM_BLK("lm_1", LM_1, 0x45000, MIXER_SDM845_MASK, 310 - &sdm845_lm_sblk, PINGPONG_1, LM_0), 309 + &sdm845_lm_sblk, PINGPONG_1, LM_0, 0), 311 310 LM_BLK("lm_2", LM_2, 0x46000, MIXER_SDM845_MASK, 312 - &sdm845_lm_sblk, PINGPONG_2, LM_5), 311 + &sdm845_lm_sblk, PINGPONG_2, LM_5, 0), 313 312 LM_BLK("lm_3", LM_3, 0x0, MIXER_SDM845_MASK, 314 - &sdm845_lm_sblk, PINGPONG_MAX, 0), 313 + &sdm845_lm_sblk, PINGPONG_MAX, 0, 0), 315 314 LM_BLK("lm_4", LM_4, 0x0, MIXER_SDM845_MASK, 316 - &sdm845_lm_sblk, PINGPONG_MAX, 0), 315 + &sdm845_lm_sblk, PINGPONG_MAX, 0, 0), 317 316 LM_BLK("lm_5", LM_5, 0x49000, MIXER_SDM845_MASK, 318 - &sdm845_lm_sblk, PINGPONG_3, LM_2), 317 + &sdm845_lm_sblk, PINGPONG_3, LM_2, 0), 319 318 }; 320 319 321 320 /* SC7180 */ ··· 331 328 332 329 static const struct dpu_lm_cfg sc7180_lm[] = { 333 330 LM_BLK("lm_0", LM_0, 0x44000, MIXER_SC7180_MASK, 334 - &sc7180_lm_sblk, PINGPONG_0, LM_1), 331 + &sc7180_lm_sblk, PINGPONG_0, LM_1, DSPP_0), 335 332 LM_BLK("lm_1", LM_1, 0x45000, MIXER_SC7180_MASK, 336 - &sc7180_lm_sblk, PINGPONG_1, LM_0), 333 + &sc7180_lm_sblk, PINGPONG_1, LM_0, 0), 337 334 }; 338 335 336 + /************************************************************* 337 + * DSPP sub blocks config 338 + *************************************************************/ 339 + #define DSPP_BLK(_name, _id, _base) \ 340 + {\ 341 + .name = _name, .id = _id, \ 342 + .base = _base, .len = 0x1800, \ 343 + .features = DSPP_SC7180_MASK, \ 344 + .sblk = NULL, \ 345 + } 346 + 347 + static const struct dpu_dspp_cfg sc7180_dspp[] = { 348 + DSPP_BLK("dspp_0", DSPP_0, 0x54000), 349 + }; 339 350 /************************************************************* 340 351 * PINGPONG sub blocks config 341 352 *************************************************************/ ··· 604 587 .sspp = sc7180_sspp, 605 588 .mixer_count = ARRAY_SIZE(sc7180_lm), 606 589 .mixer = sc7180_lm, 590 + .dspp_count = ARRAY_SIZE(sc7180_dspp), 591 + .dspp = sc7180_dspp, 607 592 .pingpong_count = ARRAY_SIZE(sc7180_pp), 608 593 .pingpong = sc7180_pp, 609 594 .intf_count = ARRAY_SIZE(sc7180_intf),
+39
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
··· 146 146 }; 147 147 148 148 /** 149 + * DSPP sub-blocks 150 + * @DPU_DSPP_PCC Panel color correction block 151 + * @DPU_DSPP_GC Gamma correction block 152 + */ 153 + enum { 154 + DPU_DSPP_PCC = 0x1, 155 + DPU_DSPP_GC, 156 + DPU_DSPP_MAX 157 + }; 158 + 159 + /** 149 160 * PINGPONG sub-blocks 150 161 * @DPU_PINGPONG_TE Tear check block 151 162 * @DPU_PINGPONG_TE2 Additional tear check block for split pipes ··· 388 377 struct dpu_pp_blk gc; 389 378 }; 390 379 380 + /** 381 + * struct dpu_dspp_sub_blks: Information of DSPP block 382 + * @gc : gamma correction block 383 + * @pcc: pixel color correction block 384 + */ 385 + struct dpu_dspp_sub_blks { 386 + struct dpu_pp_blk gc; 387 + struct dpu_pp_blk pcc; 388 + }; 389 + 391 390 struct dpu_pingpong_sub_blks { 392 391 struct dpu_pp_blk te; 393 392 struct dpu_pp_blk te2; ··· 492 471 DPU_HW_BLK_INFO; 493 472 const struct dpu_lm_sub_blks *sblk; 494 473 u32 pingpong; 474 + u32 dspp; 495 475 unsigned long lm_pair_mask; 476 + }; 477 + 478 + /** 479 + * struct dpu_dspp_cfg - information of DSPP blocks 480 + * @id enum identifying this block 481 + * @base register offset of this block 482 + * @features bit mask identifying sub-blocks/features 483 + * supported by this block 484 + * @sblk sub-blocks information 485 + */ 486 + struct dpu_dspp_cfg { 487 + DPU_HW_BLK_INFO; 488 + const struct dpu_dspp_sub_blks *sblk; 496 489 }; 497 490 498 491 /** ··· 723 688 724 689 u32 ad_count; 725 690 691 + u32 dspp_count; 692 + const struct dpu_dspp_cfg *dspp; 693 + 726 694 /* Add additional block data structures here */ 727 695 728 696 struct dpu_perf_cfg perf; ··· 754 716 #define BLK_PINGPONG(s) ((s)->pingpong) 755 717 #define BLK_INTF(s) ((s)->intf) 756 718 #define BLK_AD(s) ((s)->ad) 719 + #define BLK_DSPP(s) ((s)->dspp) 757 720 758 721 /** 759 722 * dpu_hw_catalog_init - dpu hardware catalog init API retrieves
+26
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
··· 272 272 return 0; 273 273 } 274 274 275 + static uint32_t dpu_hw_ctl_get_bitmask_dspp(struct dpu_hw_ctl *ctx, 276 + enum dpu_dspp dspp) 277 + { 278 + uint32_t flushbits = 0; 279 + 280 + switch (dspp) { 281 + case DSPP_0: 282 + flushbits = BIT(13); 283 + break; 284 + case DSPP_1: 285 + flushbits = BIT(14); 286 + break; 287 + case DSPP_2: 288 + flushbits = BIT(15); 289 + break; 290 + case DSPP_3: 291 + flushbits = BIT(21); 292 + break; 293 + default: 294 + return 0; 295 + } 296 + 297 + return flushbits; 298 + } 299 + 275 300 static u32 dpu_hw_ctl_poll_reset_status(struct dpu_hw_ctl *ctx, u32 timeout_us) 276 301 { 277 302 struct dpu_hw_blk_reg_map *c = &ctx->hw; ··· 573 548 ops->setup_blendstage = dpu_hw_ctl_setup_blendstage; 574 549 ops->get_bitmask_sspp = dpu_hw_ctl_get_bitmask_sspp; 575 550 ops->get_bitmask_mixer = dpu_hw_ctl_get_bitmask_mixer; 551 + ops->get_bitmask_dspp = dpu_hw_ctl_get_bitmask_dspp; 576 552 }; 577 553 578 554 static struct dpu_hw_blk_ops dpu_hw_ops;
+3
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
··· 139 139 uint32_t (*get_bitmask_mixer)(struct dpu_hw_ctl *ctx, 140 140 enum dpu_lm blk); 141 141 142 + uint32_t (*get_bitmask_dspp)(struct dpu_hw_ctl *ctx, 143 + enum dpu_dspp blk); 144 + 142 145 /** 143 146 * Query the value of the intf flush mask 144 147 * No effect on hardware
+82
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. 3 + */ 4 + 5 + #include "dpu_hwio.h" 6 + #include "dpu_hw_catalog.h" 7 + #include "dpu_hw_lm.h" 8 + #include "dpu_hw_dspp.h" 9 + #include "dpu_kms.h" 10 + 11 + 12 + static void _setup_dspp_ops(struct dpu_hw_dspp *c, 13 + unsigned long features) 14 + { 15 + return; 16 + } 17 + 18 + static const struct dpu_dspp_cfg *_dspp_offset(enum dpu_dspp dspp, 19 + const struct dpu_mdss_cfg *m, 20 + void __iomem *addr, 21 + struct dpu_hw_blk_reg_map *b) 22 + { 23 + int i; 24 + 25 + if (!m || !addr || !b) 26 + return ERR_PTR(-EINVAL); 27 + 28 + for (i = 0; i < m->dspp_count; i++) { 29 + if (dspp == m->dspp[i].id) { 30 + b->base_off = addr; 31 + b->blk_off = m->dspp[i].base; 32 + b->length = m->dspp[i].len; 33 + b->hwversion = m->hwversion; 34 + b->log_mask = DPU_DBG_MASK_DSPP; 35 + return &m->dspp[i]; 36 + } 37 + } 38 + 39 + return ERR_PTR(-EINVAL); 40 + } 41 + 42 + static struct dpu_hw_blk_ops dpu_hw_ops; 43 + 44 + struct dpu_hw_dspp *dpu_hw_dspp_init(enum dpu_dspp idx, 45 + void __iomem *addr, 46 + const struct dpu_mdss_cfg *m) 47 + { 48 + struct dpu_hw_dspp *c; 49 + const struct dpu_dspp_cfg *cfg; 50 + 51 + if (!addr || !m) 52 + return ERR_PTR(-EINVAL); 53 + 54 + c = kzalloc(sizeof(*c), GFP_KERNEL); 55 + if (!c) 56 + return ERR_PTR(-ENOMEM); 57 + 58 + cfg = _dspp_offset(idx, m, addr, &c->hw); 59 + if (IS_ERR_OR_NULL(cfg)) { 60 + kfree(c); 61 + return ERR_PTR(-EINVAL); 62 + } 63 + 64 + /* Assign ops */ 65 + c->idx = idx; 66 + c->cap = cfg; 67 + _setup_dspp_ops(c, c->cap->features); 68 + 69 + dpu_hw_blk_init(&c->base, DPU_HW_BLK_DSPP, idx, &dpu_hw_ops); 70 + 71 + return c; 72 + } 73 + 74 + void dpu_hw_dspp_destroy(struct dpu_hw_dspp *dspp) 75 + { 76 + if (dspp) 77 + dpu_hw_blk_destroy(&dspp->base); 78 + 79 + kfree(dspp); 80 + } 81 + 82 +
+69
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. 3 + */ 4 + 5 + #ifndef _DPU_HW_DSPP_H 6 + #define _DPU_HW_DSPP_H 7 + 8 + #include "dpu_hw_blk.h" 9 + 10 + struct dpu_hw_dspp; 11 + 12 + /** 13 + * struct dpu_hw_dspp_ops - interface to the dspp hardware driver functions 14 + * Caller must call the init function to get the dspp context for each dspp 15 + * Assumption is these functions will be called after clocks are enabled 16 + */ 17 + struct dpu_hw_dspp_ops { 18 + 19 + void (*dummy)(struct dpu_hw_dspp *ctx); 20 + }; 21 + 22 + /** 23 + * struct dpu_hw_dspp - dspp description 24 + * @base: Hardware block base structure 25 + * @hw: Block hardware details 26 + * @idx: DSPP index 27 + * @cap: Pointer to layer_cfg 28 + * @ops: Pointer to operations possible for this DSPP 29 + */ 30 + struct dpu_hw_dspp { 31 + struct dpu_hw_blk base; 32 + struct dpu_hw_blk_reg_map hw; 33 + 34 + /* dspp */ 35 + int idx; 36 + const struct dpu_dspp_cfg *cap; 37 + 38 + /* Ops */ 39 + struct dpu_hw_dspp_ops ops; 40 + }; 41 + 42 + /** 43 + * dpu_hw_dspp - convert base object dpu_hw_base to container 44 + * @hw: Pointer to base hardware block 45 + * return: Pointer to hardware block container 46 + */ 47 + static inline struct dpu_hw_dspp *to_dpu_hw_dspp(struct dpu_hw_blk *hw) 48 + { 49 + return container_of(hw, struct dpu_hw_dspp, base); 50 + } 51 + 52 + /** 53 + * dpu_hw_dspp_init - initializes the dspp hw driver object. 54 + * should be called once before accessing every dspp. 55 + * @idx: DSPP index for which driver object is required 56 + * @addr: Mapped register io address of MDP 57 + * @Return: pointer to structure or ERR_PTR 58 + */ 59 + struct dpu_hw_dspp *dpu_hw_dspp_init(enum dpu_dspp idx, 60 + void __iomem *addr, const struct dpu_mdss_cfg *m); 61 + 62 + /** 63 + * dpu_hw_dspp_destroy(): Destroys DSPP driver context 64 + * @dspp: Pointer to DSPP driver context 65 + */ 66 + void dpu_hw_dspp_destroy(struct dpu_hw_dspp *dspp); 67 + 68 + #endif /*_DPU_HW_DSPP_H */ 69 +
+2
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
··· 95 95 DPU_HW_BLK_PINGPONG, 96 96 DPU_HW_BLK_INTF, 97 97 DPU_HW_BLK_WB, 98 + DPU_HW_BLK_DSPP, 98 99 DPU_HW_BLK_MAX, 99 100 }; 100 101 ··· 426 425 #define DPU_DBG_MASK_TOP (1 << 7) 427 426 #define DPU_DBG_MASK_VBIF (1 << 8) 428 427 #define DPU_DBG_MASK_ROT (1 << 9) 428 + #define DPU_DBG_MASK_DSPP (1 << 10) 429 429 430 430 #endif /* _DPU_HW_MDSS_H */
+1
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
··· 158 158 uint32_t mixer_to_enc_id[LM_MAX - LM_0]; 159 159 uint32_t ctl_to_enc_id[CTL_MAX - CTL_0]; 160 160 uint32_t intf_to_enc_id[INTF_MAX - INTF_0]; 161 + uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0]; 161 162 }; 162 163 163 164 struct dpu_global_state
+54 -4
drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
··· 9 9 #include "dpu_hw_ctl.h" 10 10 #include "dpu_hw_pingpong.h" 11 11 #include "dpu_hw_intf.h" 12 + #include "dpu_hw_dspp.h" 12 13 #include "dpu_encoder.h" 13 14 #include "dpu_trace.h" 14 15 ··· 175 174 rm->ctl_blks[ctl->id - CTL_0] = &hw->base; 176 175 } 177 176 177 + for (i = 0; i < cat->dspp_count; i++) { 178 + struct dpu_hw_dspp *hw; 179 + const struct dpu_dspp_cfg *dspp = &cat->dspp[i]; 180 + 181 + if (dspp->id < DSPP_0 || dspp->id >= DSPP_MAX) { 182 + DPU_ERROR("skip dspp %d with invalid id\n", dspp->id); 183 + continue; 184 + } 185 + hw = dpu_hw_dspp_init(dspp->id, mmio, cat); 186 + if (IS_ERR_OR_NULL(hw)) { 187 + rc = PTR_ERR(hw); 188 + DPU_ERROR("failed dspp object creation: err %d\n", rc); 189 + goto fail; 190 + } 191 + rm->dspp_blks[dspp->id - DSPP_0] = &hw->base; 192 + } 193 + 178 194 return 0; 179 195 180 196 fail: ··· 240 222 * if lm, and all other hardwired blocks connected to the lm (pp) is 241 223 * available and appropriate 242 224 * @pp_idx: output parameter, index of pingpong block attached to the layer 243 - * mixer in rm->pongpong_blks[]. 225 + * mixer in rm->pingpong_blks[]. 226 + * @dspp_idx: output parameter, index of dspp block attached to the layer 227 + * mixer in rm->dspp_blks[]. 228 + * @reqs: input parameter, rm requirements for HW blocks needed in the 229 + * datapath. 244 230 * @Return: true if lm matches all requirements, false otherwise 245 231 */ 246 232 static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm, 247 233 struct dpu_global_state *global_state, 248 - uint32_t enc_id, int lm_idx, int *pp_idx) 234 + uint32_t enc_id, int lm_idx, int *pp_idx, int *dspp_idx, 235 + struct dpu_rm_requirements *reqs) 249 236 { 250 237 const struct dpu_lm_cfg *lm_cfg; 251 238 int idx; ··· 274 251 return false; 275 252 } 276 253 *pp_idx = idx; 254 + 255 + if (!reqs->topology.num_dspp) 256 + return true; 257 + 258 + idx = lm_cfg->dspp - DSPP_0; 259 + if (idx < 0 || idx >= ARRAY_SIZE(rm->dspp_blks)) { 260 + DPU_ERROR("failed to get dspp on lm %d\n", lm_cfg->dspp); 261 + return false; 262 + } 263 + 264 + if (reserved_by_other(global_state->dspp_to_enc_id, idx, enc_id)) { 265 + DPU_DEBUG("lm %d dspp %d already reserved\n", lm_cfg->id, 266 + lm_cfg->dspp); 267 + return false; 268 + } 269 + *dspp_idx = idx; 270 + 277 271 return true; 278 272 } 279 273 ··· 302 262 { 303 263 int lm_idx[MAX_BLOCKS]; 304 264 int pp_idx[MAX_BLOCKS]; 265 + int dspp_idx[MAX_BLOCKS] = {0}; 305 266 int i, j, lm_count = 0; 306 267 307 268 if (!reqs->topology.num_lm) { ··· 320 279 lm_idx[lm_count] = i; 321 280 322 281 if (!_dpu_rm_check_lm_and_get_connected_blks(rm, global_state, 323 - enc_id, i, &pp_idx[lm_count])) { 282 + enc_id, i, &pp_idx[lm_count], 283 + &dspp_idx[lm_count], reqs)) { 324 284 continue; 325 285 } 326 286 ··· 341 299 342 300 if (!_dpu_rm_check_lm_and_get_connected_blks(rm, 343 301 global_state, enc_id, j, 344 - &pp_idx[lm_count])) { 302 + &pp_idx[lm_count], &dspp_idx[lm_count], 303 + reqs)) { 345 304 continue; 346 305 } 347 306 ··· 359 316 for (i = 0; i < lm_count; i++) { 360 317 global_state->mixer_to_enc_id[lm_idx[i]] = enc_id; 361 318 global_state->pingpong_to_enc_id[pp_idx[i]] = enc_id; 319 + global_state->dspp_to_enc_id[dspp_idx[i]] = 320 + reqs->topology.num_dspp ? enc_id : 0; 362 321 363 322 trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, enc_id, 364 323 pp_idx[i] + PINGPONG_0); ··· 604 559 hw_blks = rm->intf_blks; 605 560 hw_to_enc_id = global_state->intf_to_enc_id; 606 561 max_blks = ARRAY_SIZE(rm->intf_blks); 562 + break; 563 + case DPU_HW_BLK_DSPP: 564 + hw_blks = rm->dspp_blks; 565 + hw_to_enc_id = global_state->dspp_to_enc_id; 566 + max_blks = ARRAY_SIZE(rm->dspp_blks); 607 567 break; 608 568 default: 609 569 DPU_ERROR("blk type %d not managed by rm\n", type);
+2
drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
··· 19 19 * @mixer_blks: array of layer mixer hardware resources 20 20 * @ctl_blks: array of ctl hardware resources 21 21 * @intf_blks: array of intf hardware resources 22 + * @dspp_blks: array of dspp hardware resources 22 23 * @lm_max_width: cached layer mixer maximum width 23 24 * @rm_lock: resource manager mutex 24 25 */ ··· 28 27 struct dpu_hw_blk *mixer_blks[LM_MAX - LM_0]; 29 28 struct dpu_hw_blk *ctl_blks[CTL_MAX - CTL_0]; 30 29 struct dpu_hw_blk *intf_blks[INTF_MAX - INTF_0]; 30 + struct dpu_hw_blk *dspp_blks[DSPP_MAX - DSPP_0]; 31 31 32 32 uint32_t lm_max_width; 33 33 };
+1
drivers/gpu/drm/msm/msm_drv.h
··· 105 105 u32 num_lm; 106 106 u32 num_enc; 107 107 u32 num_intf; 108 + u32 num_dspp; 108 109 }; 109 110 110 111 /**