Loading msm/sde/sde_hw_catalog.c +8 −1 Original line number Diff line number Diff line Loading @@ -297,6 +297,7 @@ enum { enum { DSC_OFF, DSC_LEN, DSC_PAIR_MASK, DSC_PROP_MAX, }; Loading Loading @@ -684,6 +685,7 @@ static struct sde_prop_type pp_prop[] = { static struct sde_prop_type dsc_prop[] = { {DSC_OFF, "qcom,sde-dsc-off", false, PROP_TYPE_U32_ARRAY}, {DSC_LEN, "qcom,sde-dsc-size", false, PROP_TYPE_U32}, {DSC_PAIR_MASK, "qcom,sde-dsc-pair-mask", false, PROP_TYPE_U32_ARRAY}, }; static struct sde_prop_type cdm_prop[] = { Loading Loading @@ -2559,7 +2561,7 @@ static int sde_dsc_parse_dt(struct device_node *np, int rc, prop_count[MAX_BLOCKS], i; struct sde_prop_value *prop_value = NULL; bool prop_exists[DSC_PROP_MAX]; u32 off_count; u32 off_count, dsc_pair_mask; struct sde_dsc_cfg *dsc; if (!sde_cfg) { Loading Loading @@ -2600,6 +2602,11 @@ static int sde_dsc_parse_dt(struct device_node *np, if (IS_SDE_CTL_REV_100(sde_cfg->ctl_rev)) set_bit(SDE_DSC_OUTPUT_CTRL, &dsc->features); dsc_pair_mask = PROP_VALUE_ACCESS(prop_value, DSC_PAIR_MASK, i); if (dsc_pair_mask) set_bit(dsc_pair_mask, dsc->dsc_pair_mask); } end: Loading msm/sde/sde_hw_catalog.h +3 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ #include <linux/msm-bus.h> #include <linux/of_fdt.h> #include <drm/drmP.h> #include "sde_hw_mdss.h" /** * Max hardware block count: For ex: max 12 SSPP pipes or Loading Loading @@ -915,9 +916,11 @@ struct sde_pingpong_cfg { * @base register offset of this block * @len: length of hardware block * @features bit mask identifying sub-blocks/features * @dsc_pair_mask: Bitmask of DSCs that can be controlled by same CTL */ struct sde_dsc_cfg { SDE_HW_BLK_INFO; DECLARE_BITMAP(dsc_pair_mask, DSC_MAX); }; /** Loading msm/sde/sde_rm.c +82 −15 Original line number Diff line number Diff line Loading @@ -1201,44 +1201,111 @@ static int _sde_rm_reserve_ctls( return 0; } static bool _sde_rm_check_dsc(struct sde_rm *rm, struct sde_rm_rsvp *rsvp, struct sde_rm_hw_blk *dsc, struct sde_rm_hw_blk *paired_dsc) { const struct sde_dsc_cfg *dsc_cfg = to_sde_hw_dsc(dsc->hw)->caps; /* Already reserved? */ if (RESERVED_BY_OTHER(dsc, rsvp)) { SDE_DEBUG("dsc %d already reserved\n", dsc_cfg->id); return false; } /* Check if this dsc is a peer of the proposed paired DSC */ if (paired_dsc) { const struct sde_dsc_cfg *paired_dsc_cfg = to_sde_hw_dsc(paired_dsc->hw)->caps; if (!test_bit(dsc_cfg->id, paired_dsc_cfg->dsc_pair_mask)) { SDE_DEBUG("dsc %d not peer of dsc %d\n", dsc_cfg->id, paired_dsc_cfg->id); return false; } } return true; } static int _sde_rm_reserve_dsc( struct sde_rm *rm, struct sde_rm_rsvp *rsvp, const struct sde_rm_topology_def *top, u8 *_dsc_ids) { struct sde_rm_hw_iter iter; struct sde_rm_hw_iter iter_i, iter_j; struct sde_rm_hw_blk *dsc[MAX_BLOCKS]; int alloc_count = 0; int num_dsc_enc = top->num_lm; int num_dsc_enc = top->num_comp_enc; int i; if (!top->num_comp_enc) return 0; sde_rm_init_hw_iter(&iter, 0, SDE_HW_BLK_DSC); sde_rm_init_hw_iter(&iter_i, 0, SDE_HW_BLK_DSC); while (_sde_rm_get_hw_locked(rm, &iter)) { if (RESERVED_BY_OTHER(iter.blk, rsvp)) /* Find a first DSC */ while (alloc_count != num_dsc_enc && _sde_rm_get_hw_locked(rm, &iter_i)) { memset(&dsc, 0, sizeof(dsc)); alloc_count = 0; if (_dsc_ids && (iter_i.blk->id != _dsc_ids[alloc_count])) continue; if (!_sde_rm_check_dsc(rm, rsvp, iter_i.blk, NULL)) continue; SDE_DEBUG("blk id = %d, _dsc_ids[%d] = %d\n", iter.blk->id, iter_i.blk->id, alloc_count, _dsc_ids ? _dsc_ids[alloc_count] : -1); if (_dsc_ids && (iter.blk->id != _dsc_ids[alloc_count])) dsc[alloc_count++] = iter_i.blk; /* Valid first dsc found, find matching peers */ sde_rm_init_hw_iter(&iter_j, 0, SDE_HW_BLK_DSC); while (alloc_count != num_dsc_enc && _sde_rm_get_hw_locked(rm, &iter_j)) { if (iter_i.blk == iter_j.blk) continue; iter.blk->rsvp_nxt = rsvp; SDE_EVT32(iter.blk->type, rsvp->enc_id, iter.blk->id); if (_dsc_ids && (iter_j.blk->id != _dsc_ids[alloc_count])) continue; if (++alloc_count == num_dsc_enc) return 0; if (!_sde_rm_check_dsc(rm, rsvp, iter_j.blk, iter_i.blk)) continue; SDE_DEBUG("blk id = %d, _dsc_ids[%d] = %d\n", iter_j.blk->id, alloc_count, _dsc_ids ? _dsc_ids[alloc_count] : -1); dsc[alloc_count++] = iter_j.blk; } } if (alloc_count != num_dsc_enc) { SDE_ERROR("couldn't reserve %d dsc blocks for enc id %d\n", num_dsc_enc, rsvp->enc_id); return -EINVAL; } return -ENAVAIL; for (i = 0; i < ARRAY_SIZE(dsc); i++) { if (!dsc[i]) break; dsc[i]->rsvp_nxt = rsvp; SDE_EVT32(dsc[i]->type, rsvp->enc_id, dsc[i]->id); } return 0; } static int _sde_rm_reserve_qdss( Loading Loading
msm/sde/sde_hw_catalog.c +8 −1 Original line number Diff line number Diff line Loading @@ -297,6 +297,7 @@ enum { enum { DSC_OFF, DSC_LEN, DSC_PAIR_MASK, DSC_PROP_MAX, }; Loading Loading @@ -684,6 +685,7 @@ static struct sde_prop_type pp_prop[] = { static struct sde_prop_type dsc_prop[] = { {DSC_OFF, "qcom,sde-dsc-off", false, PROP_TYPE_U32_ARRAY}, {DSC_LEN, "qcom,sde-dsc-size", false, PROP_TYPE_U32}, {DSC_PAIR_MASK, "qcom,sde-dsc-pair-mask", false, PROP_TYPE_U32_ARRAY}, }; static struct sde_prop_type cdm_prop[] = { Loading Loading @@ -2559,7 +2561,7 @@ static int sde_dsc_parse_dt(struct device_node *np, int rc, prop_count[MAX_BLOCKS], i; struct sde_prop_value *prop_value = NULL; bool prop_exists[DSC_PROP_MAX]; u32 off_count; u32 off_count, dsc_pair_mask; struct sde_dsc_cfg *dsc; if (!sde_cfg) { Loading Loading @@ -2600,6 +2602,11 @@ static int sde_dsc_parse_dt(struct device_node *np, if (IS_SDE_CTL_REV_100(sde_cfg->ctl_rev)) set_bit(SDE_DSC_OUTPUT_CTRL, &dsc->features); dsc_pair_mask = PROP_VALUE_ACCESS(prop_value, DSC_PAIR_MASK, i); if (dsc_pair_mask) set_bit(dsc_pair_mask, dsc->dsc_pair_mask); } end: Loading
msm/sde/sde_hw_catalog.h +3 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ #include <linux/msm-bus.h> #include <linux/of_fdt.h> #include <drm/drmP.h> #include "sde_hw_mdss.h" /** * Max hardware block count: For ex: max 12 SSPP pipes or Loading Loading @@ -915,9 +916,11 @@ struct sde_pingpong_cfg { * @base register offset of this block * @len: length of hardware block * @features bit mask identifying sub-blocks/features * @dsc_pair_mask: Bitmask of DSCs that can be controlled by same CTL */ struct sde_dsc_cfg { SDE_HW_BLK_INFO; DECLARE_BITMAP(dsc_pair_mask, DSC_MAX); }; /** Loading
msm/sde/sde_rm.c +82 −15 Original line number Diff line number Diff line Loading @@ -1201,44 +1201,111 @@ static int _sde_rm_reserve_ctls( return 0; } static bool _sde_rm_check_dsc(struct sde_rm *rm, struct sde_rm_rsvp *rsvp, struct sde_rm_hw_blk *dsc, struct sde_rm_hw_blk *paired_dsc) { const struct sde_dsc_cfg *dsc_cfg = to_sde_hw_dsc(dsc->hw)->caps; /* Already reserved? */ if (RESERVED_BY_OTHER(dsc, rsvp)) { SDE_DEBUG("dsc %d already reserved\n", dsc_cfg->id); return false; } /* Check if this dsc is a peer of the proposed paired DSC */ if (paired_dsc) { const struct sde_dsc_cfg *paired_dsc_cfg = to_sde_hw_dsc(paired_dsc->hw)->caps; if (!test_bit(dsc_cfg->id, paired_dsc_cfg->dsc_pair_mask)) { SDE_DEBUG("dsc %d not peer of dsc %d\n", dsc_cfg->id, paired_dsc_cfg->id); return false; } } return true; } static int _sde_rm_reserve_dsc( struct sde_rm *rm, struct sde_rm_rsvp *rsvp, const struct sde_rm_topology_def *top, u8 *_dsc_ids) { struct sde_rm_hw_iter iter; struct sde_rm_hw_iter iter_i, iter_j; struct sde_rm_hw_blk *dsc[MAX_BLOCKS]; int alloc_count = 0; int num_dsc_enc = top->num_lm; int num_dsc_enc = top->num_comp_enc; int i; if (!top->num_comp_enc) return 0; sde_rm_init_hw_iter(&iter, 0, SDE_HW_BLK_DSC); sde_rm_init_hw_iter(&iter_i, 0, SDE_HW_BLK_DSC); while (_sde_rm_get_hw_locked(rm, &iter)) { if (RESERVED_BY_OTHER(iter.blk, rsvp)) /* Find a first DSC */ while (alloc_count != num_dsc_enc && _sde_rm_get_hw_locked(rm, &iter_i)) { memset(&dsc, 0, sizeof(dsc)); alloc_count = 0; if (_dsc_ids && (iter_i.blk->id != _dsc_ids[alloc_count])) continue; if (!_sde_rm_check_dsc(rm, rsvp, iter_i.blk, NULL)) continue; SDE_DEBUG("blk id = %d, _dsc_ids[%d] = %d\n", iter.blk->id, iter_i.blk->id, alloc_count, _dsc_ids ? _dsc_ids[alloc_count] : -1); if (_dsc_ids && (iter.blk->id != _dsc_ids[alloc_count])) dsc[alloc_count++] = iter_i.blk; /* Valid first dsc found, find matching peers */ sde_rm_init_hw_iter(&iter_j, 0, SDE_HW_BLK_DSC); while (alloc_count != num_dsc_enc && _sde_rm_get_hw_locked(rm, &iter_j)) { if (iter_i.blk == iter_j.blk) continue; iter.blk->rsvp_nxt = rsvp; SDE_EVT32(iter.blk->type, rsvp->enc_id, iter.blk->id); if (_dsc_ids && (iter_j.blk->id != _dsc_ids[alloc_count])) continue; if (++alloc_count == num_dsc_enc) return 0; if (!_sde_rm_check_dsc(rm, rsvp, iter_j.blk, iter_i.blk)) continue; SDE_DEBUG("blk id = %d, _dsc_ids[%d] = %d\n", iter_j.blk->id, alloc_count, _dsc_ids ? _dsc_ids[alloc_count] : -1); dsc[alloc_count++] = iter_j.blk; } } if (alloc_count != num_dsc_enc) { SDE_ERROR("couldn't reserve %d dsc blocks for enc id %d\n", num_dsc_enc, rsvp->enc_id); return -EINVAL; } return -ENAVAIL; for (i = 0; i < ARRAY_SIZE(dsc); i++) { if (!dsc[i]) break; dsc[i]->rsvp_nxt = rsvp; SDE_EVT32(dsc[i]->type, rsvp->enc_id, dsc[i]->id); } return 0; } static int _sde_rm_reserve_qdss( Loading