b5b1ea1e4de63dfa9bbe20023440783cc1bae0e2
[linux-2.6-microblaze.git] / drivers / gpu / drm / msm / disp / dpu1 / dpu_rm.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
4  */
5
6 #define pr_fmt(fmt)     "[drm:%s] " fmt, __func__
7 #include "dpu_kms.h"
8 #include "dpu_hw_lm.h"
9 #include "dpu_hw_ctl.h"
10 #include "dpu_hw_pingpong.h"
11 #include "dpu_hw_intf.h"
12 #include "dpu_hw_dspp.h"
13 #include "dpu_hw_merge3d.h"
14 #include "dpu_encoder.h"
15 #include "dpu_trace.h"
16
17
18 static inline bool reserved_by_other(uint32_t *res_map, int idx,
19                                      uint32_t enc_id)
20 {
21         return res_map[idx] && res_map[idx] != enc_id;
22 }
23
24 /**
25  * struct dpu_rm_requirements - Reservation requirements parameter bundle
26  * @topology:  selected topology for the display
27  * @hw_res:        Hardware resources required as reported by the encoders
28  */
29 struct dpu_rm_requirements {
30         struct msm_display_topology topology;
31         struct dpu_encoder_hw_resources hw_res;
32 };
33
34 int dpu_rm_destroy(struct dpu_rm *rm)
35 {
36         int i;
37
38         for (i = 0; i < ARRAY_SIZE(rm->pingpong_blks); i++) {
39                 struct dpu_hw_pingpong *hw;
40
41                 if (rm->pingpong_blks[i]) {
42                         hw = to_dpu_hw_pingpong(rm->pingpong_blks[i]);
43                         dpu_hw_pingpong_destroy(hw);
44                 }
45         }
46         for (i = 0; i < ARRAY_SIZE(rm->merge_3d_blks); i++) {
47                 struct dpu_hw_merge_3d *hw;
48
49                 if (rm->merge_3d_blks[i]) {
50                         hw = to_dpu_hw_merge_3d(rm->merge_3d_blks[i]);
51                         dpu_hw_merge_3d_destroy(hw);
52                 }
53         }
54         for (i = 0; i < ARRAY_SIZE(rm->mixer_blks); i++) {
55                 struct dpu_hw_mixer *hw;
56
57                 if (rm->mixer_blks[i]) {
58                         hw = to_dpu_hw_mixer(rm->mixer_blks[i]);
59                         dpu_hw_lm_destroy(hw);
60                 }
61         }
62         for (i = 0; i < ARRAY_SIZE(rm->ctl_blks); i++) {
63                 struct dpu_hw_ctl *hw;
64
65                 if (rm->ctl_blks[i]) {
66                         hw = to_dpu_hw_ctl(rm->ctl_blks[i]);
67                         dpu_hw_ctl_destroy(hw);
68                 }
69         }
70         for (i = 0; i < ARRAY_SIZE(rm->intf_blks); i++) {
71                 struct dpu_hw_intf *hw;
72
73                 if (rm->intf_blks[i]) {
74                         hw = to_dpu_hw_intf(rm->intf_blks[i]);
75                         dpu_hw_intf_destroy(hw);
76                 }
77         }
78
79         return 0;
80 }
81
82 int dpu_rm_init(struct dpu_rm *rm,
83                 struct dpu_mdss_cfg *cat,
84                 void __iomem *mmio)
85 {
86         int rc, i;
87
88         if (!rm || !cat || !mmio) {
89                 DPU_ERROR("invalid kms\n");
90                 return -EINVAL;
91         }
92
93         /* Clear, setup lists */
94         memset(rm, 0, sizeof(*rm));
95
96         /* Interrogate HW catalog and create tracking items for hw blocks */
97         for (i = 0; i < cat->mixer_count; i++) {
98                 struct dpu_hw_mixer *hw;
99                 const struct dpu_lm_cfg *lm = &cat->mixer[i];
100
101                 if (lm->pingpong == PINGPONG_MAX) {
102                         DPU_DEBUG("skip mixer %d without pingpong\n", lm->id);
103                         continue;
104                 }
105
106                 if (lm->id < LM_0 || lm->id >= LM_MAX) {
107                         DPU_ERROR("skip mixer %d with invalid id\n", lm->id);
108                         continue;
109                 }
110                 hw = dpu_hw_lm_init(lm->id, mmio, cat);
111                 if (IS_ERR_OR_NULL(hw)) {
112                         rc = PTR_ERR(hw);
113                         DPU_ERROR("failed lm object creation: err %d\n", rc);
114                         goto fail;
115                 }
116                 rm->mixer_blks[lm->id - LM_0] = &hw->base;
117         }
118
119         for (i = 0; i < cat->merge_3d_count; i++) {
120                 struct dpu_hw_merge_3d *hw;
121                 const struct dpu_merge_3d_cfg *merge_3d = &cat->merge_3d[i];
122
123                 if (merge_3d->id < MERGE_3D_0 || merge_3d->id >= MERGE_3D_MAX) {
124                         DPU_ERROR("skip merge_3d %d with invalid id\n", merge_3d->id);
125                         continue;
126                 }
127                 hw = dpu_hw_merge_3d_init(merge_3d->id, mmio, cat);
128                 if (IS_ERR_OR_NULL(hw)) {
129                         rc = PTR_ERR(hw);
130                         DPU_ERROR("failed merge_3d object creation: err %d\n",
131                                 rc);
132                         goto fail;
133                 }
134                 rm->merge_3d_blks[merge_3d->id - MERGE_3D_0] = &hw->base;
135         }
136
137         for (i = 0; i < cat->pingpong_count; i++) {
138                 struct dpu_hw_pingpong *hw;
139                 const struct dpu_pingpong_cfg *pp = &cat->pingpong[i];
140
141                 if (pp->id < PINGPONG_0 || pp->id >= PINGPONG_MAX) {
142                         DPU_ERROR("skip pingpong %d with invalid id\n", pp->id);
143                         continue;
144                 }
145                 hw = dpu_hw_pingpong_init(pp->id, mmio, cat);
146                 if (IS_ERR_OR_NULL(hw)) {
147                         rc = PTR_ERR(hw);
148                         DPU_ERROR("failed pingpong object creation: err %d\n",
149                                 rc);
150                         goto fail;
151                 }
152                 if (pp->merge_3d && pp->merge_3d < MERGE_3D_MAX)
153                         hw->merge_3d = to_dpu_hw_merge_3d(rm->merge_3d_blks[pp->merge_3d - MERGE_3D_0]);
154                 rm->pingpong_blks[pp->id - PINGPONG_0] = &hw->base;
155         }
156
157         for (i = 0; i < cat->intf_count; i++) {
158                 struct dpu_hw_intf *hw;
159                 const struct dpu_intf_cfg *intf = &cat->intf[i];
160
161                 if (intf->type == INTF_NONE) {
162                         DPU_DEBUG("skip intf %d with type none\n", i);
163                         continue;
164                 }
165                 if (intf->id < INTF_0 || intf->id >= INTF_MAX) {
166                         DPU_ERROR("skip intf %d with invalid id\n", intf->id);
167                         continue;
168                 }
169                 hw = dpu_hw_intf_init(intf->id, mmio, cat);
170                 if (IS_ERR_OR_NULL(hw)) {
171                         rc = PTR_ERR(hw);
172                         DPU_ERROR("failed intf object creation: err %d\n", rc);
173                         goto fail;
174                 }
175                 rm->intf_blks[intf->id - INTF_0] = &hw->base;
176         }
177
178         for (i = 0; i < cat->ctl_count; i++) {
179                 struct dpu_hw_ctl *hw;
180                 const struct dpu_ctl_cfg *ctl = &cat->ctl[i];
181
182                 if (ctl->id < CTL_0 || ctl->id >= CTL_MAX) {
183                         DPU_ERROR("skip ctl %d with invalid id\n", ctl->id);
184                         continue;
185                 }
186                 hw = dpu_hw_ctl_init(ctl->id, mmio, cat);
187                 if (IS_ERR_OR_NULL(hw)) {
188                         rc = PTR_ERR(hw);
189                         DPU_ERROR("failed ctl object creation: err %d\n", rc);
190                         goto fail;
191                 }
192                 rm->ctl_blks[ctl->id - CTL_0] = &hw->base;
193         }
194
195         for (i = 0; i < cat->dspp_count; i++) {
196                 struct dpu_hw_dspp *hw;
197                 const struct dpu_dspp_cfg *dspp = &cat->dspp[i];
198
199                 if (dspp->id < DSPP_0 || dspp->id >= DSPP_MAX) {
200                         DPU_ERROR("skip dspp %d with invalid id\n", dspp->id);
201                         continue;
202                 }
203                 hw = dpu_hw_dspp_init(dspp->id, mmio, cat);
204                 if (IS_ERR_OR_NULL(hw)) {
205                         rc = PTR_ERR(hw);
206                         DPU_ERROR("failed dspp object creation: err %d\n", rc);
207                         goto fail;
208                 }
209                 rm->dspp_blks[dspp->id - DSPP_0] = &hw->base;
210         }
211
212         return 0;
213
214 fail:
215         dpu_rm_destroy(rm);
216
217         return rc ? rc : -EFAULT;
218 }
219
220 static bool _dpu_rm_needs_split_display(const struct msm_display_topology *top)
221 {
222         return top->num_intf > 1;
223 }
224
225 /**
226  * _dpu_rm_check_lm_peer - check if a mixer is a peer of the primary
227  * @rm: dpu resource manager handle
228  * @primary_idx: index of primary mixer in rm->mixer_blks[]
229  * @peer_idx: index of other mixer in rm->mixer_blks[]
230  * Return: true if rm->mixer_blks[peer_idx] is a peer of
231  *          rm->mixer_blks[primary_idx]
232  */
233 static bool _dpu_rm_check_lm_peer(struct dpu_rm *rm, int primary_idx,
234                 int peer_idx)
235 {
236         const struct dpu_lm_cfg *prim_lm_cfg;
237         const struct dpu_lm_cfg *peer_cfg;
238
239         prim_lm_cfg = to_dpu_hw_mixer(rm->mixer_blks[primary_idx])->cap;
240         peer_cfg = to_dpu_hw_mixer(rm->mixer_blks[peer_idx])->cap;
241
242         if (!test_bit(peer_cfg->id, &prim_lm_cfg->lm_pair_mask)) {
243                 DPU_DEBUG("lm %d not peer of lm %d\n", peer_cfg->id,
244                                 peer_cfg->id);
245                 return false;
246         }
247         return true;
248 }
249
250 /**
251  * _dpu_rm_check_lm_and_get_connected_blks - check if proposed layer mixer meets
252  *      proposed use case requirements, incl. hardwired dependent blocks like
253  *      pingpong
254  * @rm: dpu resource manager handle
255  * @global_state: resources shared across multiple kms objects
256  * @enc_id: encoder id requesting for allocation
257  * @lm_idx: index of proposed layer mixer in rm->mixer_blks[], function checks
258  *      if lm, and all other hardwired blocks connected to the lm (pp) is
259  *      available and appropriate
260  * @pp_idx: output parameter, index of pingpong block attached to the layer
261  *      mixer in rm->pingpong_blks[].
262  * @dspp_idx: output parameter, index of dspp block attached to the layer
263  *      mixer in rm->dspp_blks[].
264  * @reqs: input parameter, rm requirements for HW blocks needed in the
265  *      datapath.
266  * Return: true if lm matches all requirements, false otherwise
267  */
268 static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
269                 struct dpu_global_state *global_state,
270                 uint32_t enc_id, int lm_idx, int *pp_idx, int *dspp_idx,
271                 struct dpu_rm_requirements *reqs)
272 {
273         const struct dpu_lm_cfg *lm_cfg;
274         int idx;
275
276         /* Already reserved? */
277         if (reserved_by_other(global_state->mixer_to_enc_id, lm_idx, enc_id)) {
278                 DPU_DEBUG("lm %d already reserved\n", lm_idx + LM_0);
279                 return false;
280         }
281
282         lm_cfg = to_dpu_hw_mixer(rm->mixer_blks[lm_idx])->cap;
283         idx = lm_cfg->pingpong - PINGPONG_0;
284         if (idx < 0 || idx >= ARRAY_SIZE(rm->pingpong_blks)) {
285                 DPU_ERROR("failed to get pp on lm %d\n", lm_cfg->pingpong);
286                 return false;
287         }
288
289         if (reserved_by_other(global_state->pingpong_to_enc_id, idx, enc_id)) {
290                 DPU_DEBUG("lm %d pp %d already reserved\n", lm_cfg->id,
291                                 lm_cfg->pingpong);
292                 return false;
293         }
294         *pp_idx = idx;
295
296         if (!reqs->topology.num_dspp)
297                 return true;
298
299         idx = lm_cfg->dspp - DSPP_0;
300         if (idx < 0 || idx >= ARRAY_SIZE(rm->dspp_blks)) {
301                 DPU_ERROR("failed to get dspp on lm %d\n", lm_cfg->dspp);
302                 return false;
303         }
304
305         if (reserved_by_other(global_state->dspp_to_enc_id, idx, enc_id)) {
306                 DPU_DEBUG("lm %d dspp %d already reserved\n", lm_cfg->id,
307                                 lm_cfg->dspp);
308                 return false;
309         }
310         *dspp_idx = idx;
311
312         return true;
313 }
314
315 static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
316                                struct dpu_global_state *global_state,
317                                uint32_t enc_id,
318                                struct dpu_rm_requirements *reqs)
319
320 {
321         int lm_idx[MAX_BLOCKS];
322         int pp_idx[MAX_BLOCKS];
323         int dspp_idx[MAX_BLOCKS] = {0};
324         int i, j, lm_count = 0;
325
326         if (!reqs->topology.num_lm) {
327                 DPU_ERROR("invalid number of lm: %d\n", reqs->topology.num_lm);
328                 return -EINVAL;
329         }
330
331         /* Find a primary mixer */
332         for (i = 0; i < ARRAY_SIZE(rm->mixer_blks) &&
333                         lm_count < reqs->topology.num_lm; i++) {
334                 if (!rm->mixer_blks[i])
335                         continue;
336
337                 lm_count = 0;
338                 lm_idx[lm_count] = i;
339
340                 if (!_dpu_rm_check_lm_and_get_connected_blks(rm, global_state,
341                                 enc_id, i, &pp_idx[lm_count],
342                                 &dspp_idx[lm_count], reqs)) {
343                         continue;
344                 }
345
346                 ++lm_count;
347
348                 /* Valid primary mixer found, find matching peers */
349                 for (j = i + 1; j < ARRAY_SIZE(rm->mixer_blks) &&
350                                 lm_count < reqs->topology.num_lm; j++) {
351                         if (!rm->mixer_blks[j])
352                                 continue;
353
354                         if (!_dpu_rm_check_lm_peer(rm, i, j)) {
355                                 DPU_DEBUG("lm %d not peer of lm %d\n", LM_0 + j,
356                                                 LM_0 + i);
357                                 continue;
358                         }
359
360                         if (!_dpu_rm_check_lm_and_get_connected_blks(rm,
361                                         global_state, enc_id, j,
362                                         &pp_idx[lm_count], &dspp_idx[lm_count],
363                                         reqs)) {
364                                 continue;
365                         }
366
367                         lm_idx[lm_count] = j;
368                         ++lm_count;
369                 }
370         }
371
372         if (lm_count != reqs->topology.num_lm) {
373                 DPU_DEBUG("unable to find appropriate mixers\n");
374                 return -ENAVAIL;
375         }
376
377         for (i = 0; i < lm_count; i++) {
378                 global_state->mixer_to_enc_id[lm_idx[i]] = enc_id;
379                 global_state->pingpong_to_enc_id[pp_idx[i]] = enc_id;
380                 global_state->dspp_to_enc_id[dspp_idx[i]] =
381                         reqs->topology.num_dspp ? enc_id : 0;
382
383                 trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, enc_id,
384                                          pp_idx[i] + PINGPONG_0);
385         }
386
387         return 0;
388 }
389
390 static int _dpu_rm_reserve_ctls(
391                 struct dpu_rm *rm,
392                 struct dpu_global_state *global_state,
393                 uint32_t enc_id,
394                 const struct msm_display_topology *top)
395 {
396         int ctl_idx[MAX_BLOCKS];
397         int i = 0, j, num_ctls;
398         bool needs_split_display;
399
400         /* each hw_intf needs its own hw_ctrl to program its control path */
401         num_ctls = top->num_intf;
402
403         needs_split_display = _dpu_rm_needs_split_display(top);
404
405         for (j = 0; j < ARRAY_SIZE(rm->ctl_blks); j++) {
406                 const struct dpu_hw_ctl *ctl;
407                 unsigned long features;
408                 bool has_split_display;
409
410                 if (!rm->ctl_blks[j])
411                         continue;
412                 if (reserved_by_other(global_state->ctl_to_enc_id, j, enc_id))
413                         continue;
414
415                 ctl = to_dpu_hw_ctl(rm->ctl_blks[j]);
416                 features = ctl->caps->features;
417                 has_split_display = BIT(DPU_CTL_SPLIT_DISPLAY) & features;
418
419                 DPU_DEBUG("ctl %d caps 0x%lX\n", j + CTL_0, features);
420
421                 if (needs_split_display != has_split_display)
422                         continue;
423
424                 ctl_idx[i] = j;
425                 DPU_DEBUG("ctl %d match\n", j + CTL_0);
426
427                 if (++i == num_ctls)
428                         break;
429
430         }
431
432         if (i != num_ctls)
433                 return -ENAVAIL;
434
435         for (i = 0; i < ARRAY_SIZE(ctl_idx) && i < num_ctls; i++) {
436                 global_state->ctl_to_enc_id[ctl_idx[i]] = enc_id;
437                 trace_dpu_rm_reserve_ctls(i + CTL_0, enc_id);
438         }
439
440         return 0;
441 }
442
443 static int _dpu_rm_reserve_intf(
444                 struct dpu_rm *rm,
445                 struct dpu_global_state *global_state,
446                 uint32_t enc_id,
447                 uint32_t id)
448 {
449         int idx = id - INTF_0;
450
451         if (idx < 0 || idx >= ARRAY_SIZE(rm->intf_blks)) {
452                 DPU_ERROR("invalid intf id: %d", id);
453                 return -EINVAL;
454         }
455
456         if (!rm->intf_blks[idx]) {
457                 DPU_ERROR("couldn't find intf id %d\n", id);
458                 return -EINVAL;
459         }
460
461         if (reserved_by_other(global_state->intf_to_enc_id, idx, enc_id)) {
462                 DPU_ERROR("intf id %d already reserved\n", id);
463                 return -ENAVAIL;
464         }
465
466         global_state->intf_to_enc_id[idx] = enc_id;
467         return 0;
468 }
469
470 static int _dpu_rm_reserve_intf_related_hw(
471                 struct dpu_rm *rm,
472                 struct dpu_global_state *global_state,
473                 uint32_t enc_id,
474                 struct dpu_encoder_hw_resources *hw_res)
475 {
476         int i, ret = 0;
477         u32 id;
478
479         for (i = 0; i < ARRAY_SIZE(hw_res->intfs); i++) {
480                 if (hw_res->intfs[i] == INTF_MODE_NONE)
481                         continue;
482                 id = i + INTF_0;
483                 ret = _dpu_rm_reserve_intf(rm, global_state, enc_id, id);
484                 if (ret)
485                         return ret;
486         }
487
488         return ret;
489 }
490
491 static int _dpu_rm_make_reservation(
492                 struct dpu_rm *rm,
493                 struct dpu_global_state *global_state,
494                 struct drm_encoder *enc,
495                 struct dpu_rm_requirements *reqs)
496 {
497         int ret;
498
499         ret = _dpu_rm_reserve_lms(rm, global_state, enc->base.id, reqs);
500         if (ret) {
501                 DPU_ERROR("unable to find appropriate mixers\n");
502                 return ret;
503         }
504
505         ret = _dpu_rm_reserve_ctls(rm, global_state, enc->base.id,
506                                 &reqs->topology);
507         if (ret) {
508                 DPU_ERROR("unable to find appropriate CTL\n");
509                 return ret;
510         }
511
512         ret = _dpu_rm_reserve_intf_related_hw(rm, global_state, enc->base.id,
513                                 &reqs->hw_res);
514         if (ret)
515                 return ret;
516
517         return ret;
518 }
519
520 static int _dpu_rm_populate_requirements(
521                 struct drm_encoder *enc,
522                 struct dpu_rm_requirements *reqs,
523                 struct msm_display_topology req_topology)
524 {
525         dpu_encoder_get_hw_resources(enc, &reqs->hw_res);
526
527         reqs->topology = req_topology;
528
529         DRM_DEBUG_KMS("num_lm: %d num_enc: %d num_intf: %d\n",
530                       reqs->topology.num_lm, reqs->topology.num_enc,
531                       reqs->topology.num_intf);
532
533         return 0;
534 }
535
536 static void _dpu_rm_clear_mapping(uint32_t *res_mapping, int cnt,
537                                   uint32_t enc_id)
538 {
539         int i;
540
541         for (i = 0; i < cnt; i++) {
542                 if (res_mapping[i] == enc_id)
543                         res_mapping[i] = 0;
544         }
545 }
546
547 void dpu_rm_release(struct dpu_global_state *global_state,
548                     struct drm_encoder *enc)
549 {
550         _dpu_rm_clear_mapping(global_state->pingpong_to_enc_id,
551                 ARRAY_SIZE(global_state->pingpong_to_enc_id), enc->base.id);
552         _dpu_rm_clear_mapping(global_state->mixer_to_enc_id,
553                 ARRAY_SIZE(global_state->mixer_to_enc_id), enc->base.id);
554         _dpu_rm_clear_mapping(global_state->ctl_to_enc_id,
555                 ARRAY_SIZE(global_state->ctl_to_enc_id), enc->base.id);
556         _dpu_rm_clear_mapping(global_state->intf_to_enc_id,
557                 ARRAY_SIZE(global_state->intf_to_enc_id), enc->base.id);
558 }
559
560 int dpu_rm_reserve(
561                 struct dpu_rm *rm,
562                 struct dpu_global_state *global_state,
563                 struct drm_encoder *enc,
564                 struct drm_crtc_state *crtc_state,
565                 struct msm_display_topology topology)
566 {
567         struct dpu_rm_requirements reqs;
568         int ret;
569
570         /* Check if this is just a page-flip */
571         if (!drm_atomic_crtc_needs_modeset(crtc_state))
572                 return 0;
573
574         if (IS_ERR(global_state)) {
575                 DPU_ERROR("failed to global state\n");
576                 return PTR_ERR(global_state);
577         }
578
579         DRM_DEBUG_KMS("reserving hw for enc %d crtc %d\n",
580                       enc->base.id, crtc_state->crtc->base.id);
581
582         ret = _dpu_rm_populate_requirements(enc, &reqs, topology);
583         if (ret) {
584                 DPU_ERROR("failed to populate hw requirements\n");
585                 return ret;
586         }
587
588         ret = _dpu_rm_make_reservation(rm, global_state, enc, &reqs);
589         if (ret)
590                 DPU_ERROR("failed to reserve hw resources: %d\n", ret);
591
592
593
594         return ret;
595 }
596
597 int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
598         struct dpu_global_state *global_state, uint32_t enc_id,
599         enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size)
600 {
601         struct dpu_hw_blk **hw_blks;
602         uint32_t *hw_to_enc_id;
603         int i, num_blks, max_blks;
604
605         switch (type) {
606         case DPU_HW_BLK_PINGPONG:
607                 hw_blks = rm->pingpong_blks;
608                 hw_to_enc_id = global_state->pingpong_to_enc_id;
609                 max_blks = ARRAY_SIZE(rm->pingpong_blks);
610                 break;
611         case DPU_HW_BLK_LM:
612                 hw_blks = rm->mixer_blks;
613                 hw_to_enc_id = global_state->mixer_to_enc_id;
614                 max_blks = ARRAY_SIZE(rm->mixer_blks);
615                 break;
616         case DPU_HW_BLK_CTL:
617                 hw_blks = rm->ctl_blks;
618                 hw_to_enc_id = global_state->ctl_to_enc_id;
619                 max_blks = ARRAY_SIZE(rm->ctl_blks);
620                 break;
621         case DPU_HW_BLK_INTF:
622                 hw_blks = rm->intf_blks;
623                 hw_to_enc_id = global_state->intf_to_enc_id;
624                 max_blks = ARRAY_SIZE(rm->intf_blks);
625                 break;
626         case DPU_HW_BLK_DSPP:
627                 hw_blks = rm->dspp_blks;
628                 hw_to_enc_id = global_state->dspp_to_enc_id;
629                 max_blks = ARRAY_SIZE(rm->dspp_blks);
630                 break;
631         default:
632                 DPU_ERROR("blk type %d not managed by rm\n", type);
633                 return 0;
634         }
635
636         num_blks = 0;
637         for (i = 0; i < max_blks; i++) {
638                 if (hw_to_enc_id[i] != enc_id)
639                         continue;
640
641                 if (num_blks == blks_size) {
642                         DPU_ERROR("More than %d resources assigned to enc %d\n",
643                                   blks_size, enc_id);
644                         break;
645                 }
646                 blks[num_blks++] = hw_blks[i];
647         }
648
649         return num_blks;
650 }