Loading msm/sde/sde_encoder_phys_wb.c +27 −43 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ Loading Loading @@ -136,25 +136,6 @@ static void sde_encoder_phys_wb_set_qos_remap( sde_vbif_set_qos_remap(phys_enc->sde_kms, &qos_params); } static u64 _sde_encoder_phys_wb_get_qos_lut(const struct sde_qos_lut_tbl *tbl, u32 total_fl) { int i; if (!tbl || !tbl->nentry || !tbl->entries) return 0; for (i = 0; i < tbl->nentry; i++) if (total_fl <= tbl->entries[i].fl) return tbl->entries[i].lut; /* if last fl is zero, use as default */ if (!tbl->entries[i-1].fl) return tbl->entries[i-1].lut; return 0; } /** * sde_encoder_phys_wb_set_qos - set QoS/danger/safe LUTs for writeback * @phys_enc: Pointer to physical encoder Loading @@ -163,14 +144,14 @@ static void sde_encoder_phys_wb_set_qos(struct sde_encoder_phys *phys_enc) { struct sde_encoder_phys_wb *wb_enc; struct sde_hw_wb *hw_wb; struct sde_hw_wb_qos_cfg qos_cfg; struct sde_mdss_cfg *catalog; struct sde_hw_wb_qos_cfg qos_cfg = {0}; struct sde_perf_cfg *perf; u32 fps_index = 0, lut_index, index, frame_rate, qos_count; if (!phys_enc || !phys_enc->sde_kms || !phys_enc->sde_kms->catalog) { SDE_ERROR("invalid parameter(s)\n"); return; } catalog = phys_enc->sde_kms->catalog; wb_enc = to_sde_encoder_phys_wb(phys_enc); if (!wb_enc->hw_wb) { Loading @@ -178,35 +159,38 @@ static void sde_encoder_phys_wb_set_qos(struct sde_encoder_phys *phys_enc) return; } perf = &phys_enc->sde_kms->catalog->perf; frame_rate = phys_enc->cached_mode.vrefresh; hw_wb = wb_enc->hw_wb; qos_count = perf->qos_refresh_count; while (qos_count && perf->qos_refresh_rate) { if (frame_rate >= perf->qos_refresh_rate[qos_count - 1]) { fps_index = qos_count - 1; break; } qos_count--; } memset(&qos_cfg, 0, sizeof(struct sde_hw_wb_qos_cfg)); qos_cfg.danger_safe_en = true; qos_cfg.danger_lut = catalog->perf.danger_lut_tbl[SDE_QOS_LUT_USAGE_NRT]; if (phys_enc->in_clone_mode) qos_cfg.safe_lut = (u32) _sde_encoder_phys_wb_get_qos_lut( &catalog->perf.sfe_lut_tbl[SDE_QOS_LUT_USAGE_CWB], 0); else qos_cfg.safe_lut = (u32) _sde_encoder_phys_wb_get_qos_lut( &catalog->perf.sfe_lut_tbl[SDE_QOS_LUT_USAGE_NRT], 0); if (phys_enc->in_clone_mode) qos_cfg.creq_lut = _sde_encoder_phys_wb_get_qos_lut( &catalog->perf.qos_lut_tbl[SDE_QOS_LUT_USAGE_CWB], 0); lut_index = SDE_QOS_LUT_USAGE_CWB; else qos_cfg.creq_lut = _sde_encoder_phys_wb_get_qos_lut( &catalog->perf.qos_lut_tbl[SDE_QOS_LUT_USAGE_NRT], 0); lut_index = SDE_QOS_LUT_USAGE_NRT; index = (fps_index * SDE_QOS_LUT_USAGE_MAX) + lut_index; if (hw_wb->ops.setup_danger_safe_lut) hw_wb->ops.setup_danger_safe_lut(hw_wb, &qos_cfg); qos_cfg.danger_lut = perf->danger_lut[index]; qos_cfg.safe_lut = (u32) perf->safe_lut[index]; qos_cfg.creq_lut = perf->creq_lut[index]; if (hw_wb->ops.setup_creq_lut) hw_wb->ops.setup_creq_lut(hw_wb, &qos_cfg); SDE_DEBUG("wb_enc:%d hw idx:%d fps:%d mode:%d luts[0x%x,0x%x 0x%llx]\n", DRMID(phys_enc->parent), hw_wb->idx - WB_0, frame_rate, phys_enc->in_clone_mode, qos_cfg.danger_lut, qos_cfg.safe_lut, qos_cfg.creq_lut); if (hw_wb->ops.setup_qos_ctrl) hw_wb->ops.setup_qos_ctrl(hw_wb, &qos_cfg); if (hw_wb->ops.setup_qos_lut) hw_wb->ops.setup_qos_lut(hw_wb, &qos_cfg); } /** Loading msm/sde/sde_hw_catalog.c +162 −184 Original line number Diff line number Diff line Loading @@ -218,25 +218,30 @@ enum { PERF_DOWNSCALING_PREFILL_LINES, PERF_XTRA_PREFILL_LINES, PERF_AMORTIZABLE_THRESHOLD, PERF_DANGER_LUT, PERF_SAFE_LUT_LINEAR, PERF_SAFE_LUT_MACROTILE, PERF_SAFE_LUT_NRT, PERF_SAFE_LUT_CWB, PERF_QOS_LUT_LINEAR, PERF_QOS_LUT_MACROTILE, PERF_QOS_LUT_NRT, PERF_QOS_LUT_CWB, PERF_NUM_MNOC_PORTS, PERF_AXI_BUS_WIDTH, PERF_CDP_SETTING, PERF_CPU_MASK, PERF_CPU_DMA_LATENCY, PERF_QOS_LUT_MACROTILE_QSEED, PERF_SAFE_LUT_MACROTILE_QSEED, PERF_NUM_MNOC_PORTS, PERF_AXI_BUS_WIDTH, PERF_PROP_MAX, }; enum { QOS_REFRESH_RATES, QOS_DANGER_LUT, QOS_SAFE_LUT_LINEAR, QOS_SAFE_LUT_MACROTILE, QOS_SAFE_LUT_NRT, QOS_SAFE_LUT_CWB, QOS_SAFE_LUT_MACROTILE_QSEED, QOS_CREQ_LUT_LINEAR, QOS_CREQ_LUT_MACROTILE, QOS_CREQ_LUT_NRT, QOS_CREQ_LUT_CWB, QOS_CREQ_LUT_MACROTILE_QSEED, QOS_PROP_MAX, }; enum { SSPP_OFF, SSPP_SIZE, Loading Loading @@ -532,37 +537,41 @@ static struct sde_prop_type sde_perf_prop[] = { false, PROP_TYPE_U32}, {PERF_AMORTIZABLE_THRESHOLD, "qcom,sde-amortizable-threshold", false, PROP_TYPE_U32}, {PERF_DANGER_LUT, "qcom,sde-danger-lut", false, PROP_TYPE_U32_ARRAY}, {PERF_SAFE_LUT_LINEAR, "qcom,sde-safe-lut-linear", false, {PERF_NUM_MNOC_PORTS, "qcom,sde-num-mnoc-ports", false, PROP_TYPE_U32}, {PERF_AXI_BUS_WIDTH, "qcom,sde-axi-bus-width", false, PROP_TYPE_U32}, {PERF_CDP_SETTING, "qcom,sde-cdp-setting", false, PROP_TYPE_U32_ARRAY}, {PERF_SAFE_LUT_MACROTILE, "qcom,sde-safe-lut-macrotile", false, {PERF_CPU_MASK, "qcom,sde-qos-cpu-mask", false, PROP_TYPE_U32}, {PERF_CPU_DMA_LATENCY, "qcom,sde-qos-cpu-dma-latency", false, PROP_TYPE_U32}, }; static struct sde_prop_type sde_qos_prop[] = { {QOS_REFRESH_RATES, "qcom,sde-qos-refresh-rates", false, PROP_TYPE_U32_ARRAY}, {QOS_DANGER_LUT, "qcom,sde-danger-lut", false, PROP_TYPE_U32_ARRAY}, {QOS_SAFE_LUT_LINEAR, "qcom,sde-safe-lut-linear", false, PROP_TYPE_U32_ARRAY}, {PERF_SAFE_LUT_NRT, "qcom,sde-safe-lut-nrt", false, {QOS_SAFE_LUT_MACROTILE, "qcom,sde-safe-lut-macrotile", false, PROP_TYPE_U32_ARRAY}, {PERF_SAFE_LUT_CWB, "qcom,sde-safe-lut-cwb", false, {QOS_SAFE_LUT_NRT, "qcom,sde-safe-lut-nrt", false, PROP_TYPE_U32_ARRAY}, {PERF_QOS_LUT_LINEAR, "qcom,sde-qos-lut-linear", false, {QOS_SAFE_LUT_CWB, "qcom,sde-safe-lut-cwb", false, PROP_TYPE_U32_ARRAY}, {PERF_QOS_LUT_MACROTILE, "qcom,sde-qos-lut-macrotile", false, {QOS_SAFE_LUT_MACROTILE_QSEED, "qcom,sde-safe-lut-macrotile-qseed", false, PROP_TYPE_U32_ARRAY}, {QOS_CREQ_LUT_LINEAR, "qcom,sde-qos-lut-linear", false, PROP_TYPE_U32_ARRAY}, {PERF_QOS_LUT_NRT, "qcom,sde-qos-lut-nrt", false, {QOS_CREQ_LUT_MACROTILE, "qcom,sde-qos-lut-macrotile", false, PROP_TYPE_U32_ARRAY}, {PERF_QOS_LUT_CWB, "qcom,sde-qos-lut-cwb", false, {QOS_CREQ_LUT_NRT, "qcom,sde-qos-lut-nrt", false, PROP_TYPE_U32_ARRAY}, {PERF_CDP_SETTING, "qcom,sde-cdp-setting", false, {QOS_CREQ_LUT_CWB, "qcom,sde-qos-lut-cwb", false, PROP_TYPE_U32_ARRAY}, {PERF_CPU_MASK, "qcom,sde-qos-cpu-mask", false, PROP_TYPE_U32}, {PERF_CPU_DMA_LATENCY, "qcom,sde-qos-cpu-dma-latency", false, PROP_TYPE_U32}, {PERF_QOS_LUT_MACROTILE_QSEED, "qcom,sde-qos-lut-macrotile-qseed", false, PROP_TYPE_U32_ARRAY}, {PERF_SAFE_LUT_MACROTILE_QSEED, "qcom,sde-safe-lut-macrotile-qseed", {QOS_CREQ_LUT_MACROTILE_QSEED, "qcom,sde-qos-lut-macrotile-qseed", false, PROP_TYPE_U32_ARRAY}, {PERF_NUM_MNOC_PORTS, "qcom,sde-num-mnoc-ports", false, PROP_TYPE_U32}, {PERF_AXI_BUS_WIDTH, "qcom,sde-axi-bus-width", false, PROP_TYPE_U32}, }; static struct sde_prop_type sspp_prop[] = { Loading Loading @@ -3580,172 +3589,116 @@ static int _sde_perf_parse_dt_validate(struct device_node *np, int *prop_count) if (rc) return rc; rc = _validate_dt_entry(np, &sde_perf_prop[PERF_DANGER_LUT], 1, &prop_count[PERF_DANGER_LUT], NULL); if (rc) return rc; rc = _validate_dt_entry(np, &sde_perf_prop[PERF_SAFE_LUT_LINEAR], 1, &prop_count[PERF_SAFE_LUT_LINEAR], NULL); if (rc) return rc; rc = _validate_dt_entry(np, &sde_perf_prop[PERF_SAFE_LUT_MACROTILE], 1, &prop_count[PERF_SAFE_LUT_MACROTILE], NULL); if (rc) return rc; rc = _validate_dt_entry(np, &sde_perf_prop[PERF_SAFE_LUT_NRT], 1, &prop_count[PERF_SAFE_LUT_NRT], NULL); if (rc) return rc; rc = _validate_dt_entry(np, &sde_perf_prop[PERF_SAFE_LUT_CWB], 1, &prop_count[PERF_SAFE_LUT_CWB], NULL); if (rc) return rc; rc = _validate_dt_entry(np, &sde_perf_prop[PERF_QOS_LUT_LINEAR], 1, &prop_count[PERF_QOS_LUT_LINEAR], NULL); if (rc) return rc; rc = _validate_dt_entry(np, &sde_perf_prop[PERF_QOS_LUT_MACROTILE], 1, &prop_count[PERF_QOS_LUT_MACROTILE], NULL); if (rc) return rc; rc = _validate_dt_entry(np, &sde_perf_prop[PERF_QOS_LUT_NRT], 1, &prop_count[PERF_QOS_LUT_NRT], NULL); if (rc) return rc; rc = _validate_dt_entry(np, &sde_perf_prop[PERF_QOS_LUT_CWB], 1, &prop_count[PERF_QOS_LUT_CWB], NULL); if (rc) return rc; rc = _validate_dt_entry(np, &sde_perf_prop[PERF_CDP_SETTING], 1, &prop_count[PERF_CDP_SETTING], NULL); if (rc) return rc; rc = _validate_dt_entry(np, &sde_perf_prop[PERF_QOS_LUT_MACROTILE_QSEED], 1, &prop_count[PERF_QOS_LUT_MACROTILE_QSEED], NULL); if (rc) return rc; rc = _validate_dt_entry(np, &sde_perf_prop[PERF_SAFE_LUT_MACROTILE_QSEED], 1, &prop_count[PERF_SAFE_LUT_MACROTILE_QSEED], NULL); return rc; } static int _sde_perf_parse_dt_cfg_qos(struct sde_mdss_cfg *cfg, int *prop_count, static int _sde_qos_parse_dt_cfg(struct sde_mdss_cfg *cfg, int *prop_count, struct sde_prop_value *prop_value, bool *prop_exists) { int j, k; int i, j; u32 qos_count = 1, index; if (prop_exists[PERF_DANGER_LUT] && prop_count[PERF_DANGER_LUT] <= SDE_QOS_LUT_USAGE_MAX) { for (j = 0; j < prop_count[PERF_DANGER_LUT]; j++) { cfg->perf.danger_lut_tbl[j] = if (prop_exists[QOS_REFRESH_RATES]) { qos_count = prop_count[QOS_REFRESH_RATES]; cfg->perf.qos_refresh_rate = kcalloc(qos_count, sizeof(u32), GFP_KERNEL); if (!cfg->perf.qos_refresh_rate) goto end; for (j = 0; j < qos_count; j++) { cfg->perf.qos_refresh_rate[j] = PROP_VALUE_ACCESS(prop_value, PERF_DANGER_LUT, j); SDE_DEBUG("danger usage:%d lut:0x%x\n", j, cfg->perf.danger_lut_tbl[j]); QOS_REFRESH_RATES, j); SDE_DEBUG("qos usage:%d refresh rate:0x%x\n", j, cfg->perf.qos_refresh_rate[j]); } } cfg->perf.qos_refresh_count = qos_count; for (j = 0; j < SDE_QOS_LUT_USAGE_MAX; j++) { static const u32 safe_key[SDE_QOS_LUT_USAGE_MAX] = { cfg->perf.danger_lut = kcalloc(qos_count, sizeof(u64) * SDE_QOS_LUT_USAGE_MAX, GFP_KERNEL); cfg->perf.safe_lut = kcalloc(qos_count, sizeof(u64) * SDE_QOS_LUT_USAGE_MAX, GFP_KERNEL); cfg->perf.creq_lut = kcalloc(qos_count, sizeof(u64) * SDE_QOS_LUT_USAGE_MAX, GFP_KERNEL); if (!cfg->perf.creq_lut || !cfg->perf.safe_lut || !cfg->perf.danger_lut) goto end; if (prop_exists[QOS_DANGER_LUT] && prop_count[QOS_DANGER_LUT] >= (SDE_QOS_LUT_USAGE_MAX * qos_count)) { for (i = 0; i < prop_count[QOS_DANGER_LUT]; i++) { cfg->perf.danger_lut[i] = PROP_VALUE_ACCESS(prop_value, QOS_DANGER_LUT, i); SDE_DEBUG("danger usage:%i lut:0x%x\n", i, cfg->perf.danger_lut[i]); } } for (i = 0; i < SDE_QOS_LUT_USAGE_MAX; i++) { static const u32 prop_creq_key[SDE_QOS_LUT_USAGE_MAX] = { [SDE_QOS_LUT_USAGE_LINEAR] = PERF_SAFE_LUT_LINEAR, QOS_CREQ_LUT_LINEAR, [SDE_QOS_LUT_USAGE_MACROTILE] = PERF_SAFE_LUT_MACROTILE, QOS_CREQ_LUT_MACROTILE, [SDE_QOS_LUT_USAGE_NRT] = PERF_SAFE_LUT_NRT, QOS_CREQ_LUT_NRT, [SDE_QOS_LUT_USAGE_CWB] = PERF_SAFE_LUT_CWB, QOS_CREQ_LUT_CWB, [SDE_QOS_LUT_USAGE_MACROTILE_QSEED] = PERF_SAFE_LUT_MACROTILE_QSEED, QOS_CREQ_LUT_MACROTILE_QSEED, }; const u32 entry_size = 2; int m, count; int key = safe_key[j]; if (!prop_exists[key]) continue; count = prop_count[key] / entry_size; cfg->perf.sfe_lut_tbl[j].entries = kcalloc(count, sizeof(struct sde_qos_lut_entry), GFP_KERNEL); if (!cfg->perf.sfe_lut_tbl[j].entries) return -ENOMEM; for (k = 0, m = 0; k < count; k++, m += entry_size) { u64 lut_lo; cfg->perf.sfe_lut_tbl[j].entries[k].fl = PROP_VALUE_ACCESS(prop_value, key, m); lut_lo = PROP_VALUE_ACCESS(prop_value, key, m + 1); cfg->perf.sfe_lut_tbl[j].entries[k].lut = lut_lo; SDE_DEBUG("safe usage:%d.%d fl:%d lut:0x%llx\n", j, k, cfg->perf.sfe_lut_tbl[j].entries[k].fl, cfg->perf.sfe_lut_tbl[j].entries[k].lut); } cfg->perf.sfe_lut_tbl[j].nentry = count; } for (j = 0; j < SDE_QOS_LUT_USAGE_MAX; j++) { static const u32 prop_key[SDE_QOS_LUT_USAGE_MAX] = { static const u32 prop_safe_key[SDE_QOS_LUT_USAGE_MAX] = { [SDE_QOS_LUT_USAGE_LINEAR] = PERF_QOS_LUT_LINEAR, QOS_SAFE_LUT_LINEAR, [SDE_QOS_LUT_USAGE_MACROTILE] = PERF_QOS_LUT_MACROTILE, QOS_SAFE_LUT_MACROTILE, [SDE_QOS_LUT_USAGE_NRT] = PERF_QOS_LUT_NRT, QOS_SAFE_LUT_NRT, [SDE_QOS_LUT_USAGE_CWB] = PERF_QOS_LUT_CWB, QOS_SAFE_LUT_CWB, [SDE_QOS_LUT_USAGE_MACROTILE_QSEED] = PERF_QOS_LUT_MACROTILE_QSEED, QOS_SAFE_LUT_MACROTILE_QSEED, }; const u32 entry_size = 3; int m, count; int key = prop_key[j]; int creq_key = prop_creq_key[i]; int safe_key = prop_safe_key[i]; u64 lut_hi, lut_lo; if (!prop_exists[key]) if (!prop_exists[creq_key] || !prop_exists[safe_key]) continue; count = prop_count[key] / entry_size; for (j = 0; j < qos_count; j++) { lut_hi = PROP_VALUE_ACCESS(prop_value, creq_key, (j * 3) + 1); lut_lo = PROP_VALUE_ACCESS(prop_value, creq_key, (j * 3) + 2); index = (j * SDE_QOS_LUT_USAGE_MAX) + i; cfg->perf.qos_lut_tbl[j].entries = kcalloc(count, sizeof(struct sde_qos_lut_entry), GFP_KERNEL); if (!cfg->perf.qos_lut_tbl[j].entries) return -ENOMEM; for (k = 0, m = 0; k < count; k++, m += entry_size) { u64 lut_hi, lut_lo; cfg->perf.qos_lut_tbl[j].entries[k].fl = PROP_VALUE_ACCESS(prop_value, key, m); lut_hi = PROP_VALUE_ACCESS(prop_value, key, m + 1); lut_lo = PROP_VALUE_ACCESS(prop_value, key, m + 2); cfg->perf.qos_lut_tbl[j].entries[k].lut = cfg->perf.creq_lut[index] = (lut_hi << 32) | lut_lo; SDE_DEBUG("usage:%d.%d fl:%d lut:0x%llx\n", j, k, cfg->perf.qos_lut_tbl[j].entries[k].fl, cfg->perf.qos_lut_tbl[j].entries[k].lut); cfg->perf.safe_lut[index] = PROP_VALUE_ACCESS(prop_value, safe_key, (j * 2) + 1); SDE_DEBUG("usage:%d creq lut:0x%llx safe:0x%x\n", index, cfg->perf.creq_lut[index], cfg->perf.safe_lut[index]); } cfg->perf.qos_lut_tbl[j].nentry = count; } return 0; end: kfree(cfg->perf.qos_refresh_rate); kfree(cfg->perf.creq_lut); kfree(cfg->perf.danger_lut); kfree(cfg->perf.safe_lut); return -ENOMEM; } static void _sde_perf_parse_dt_cfg_populate(struct sde_mdss_cfg *cfg, Loading Loading @@ -3854,11 +3807,6 @@ static int _sde_perf_parse_dt_cfg(struct device_node *np, _sde_perf_parse_dt_cfg_populate(cfg, prop_count, prop_value, prop_exists); rc = _sde_perf_parse_dt_cfg_qos(cfg, prop_count, prop_value, prop_exists); if (rc) return rc; if (prop_exists[PERF_CDP_SETTING]) { const u32 prop_size = 2; u32 count = prop_count[PERF_CDP_SETTING] / prop_size; Loading Loading @@ -3929,6 +3877,43 @@ static int sde_perf_parse_dt(struct device_node *np, struct sde_mdss_cfg *cfg) return rc; } static int sde_qos_parse_dt(struct device_node *np, struct sde_mdss_cfg *cfg) { int rc, prop_count[QOS_PROP_MAX]; struct sde_prop_value *prop_value = NULL; bool prop_exists[QOS_PROP_MAX]; if (!cfg) { SDE_ERROR("invalid argument\n"); rc = -EINVAL; goto end; } prop_value = kzalloc(QOS_PROP_MAX * sizeof(struct sde_prop_value), GFP_KERNEL); if (!prop_value) { rc = -ENOMEM; goto end; } rc = _validate_dt_entry(np, sde_qos_prop, ARRAY_SIZE(sde_qos_prop), prop_count, NULL); if (rc) goto freeprop; rc = _read_dt_entry(np, sde_qos_prop, ARRAY_SIZE(sde_qos_prop), prop_count, prop_exists, prop_value); if (rc) goto freeprop; rc = _sde_qos_parse_dt_cfg(cfg, prop_count, prop_value, prop_exists); freeprop: kfree(prop_value); end: return rc; } static int sde_parse_merge_3d_dt(struct device_node *np, struct sde_mdss_cfg *sde_cfg) { Loading Loading @@ -4225,7 +4210,6 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) sde_cfg->sui_misr_supported = true; sde_cfg->sui_block_xin_mask = 0x3F71; sde_cfg->has_sui_blendstage = true; sde_cfg->has_qos_fl_nocalc = true; sde_cfg->has_3d_merge_reset = true; clear_bit(MDSS_INTR_LTM_0_INTR, sde_cfg->mdss_irqs); clear_bit(MDSS_INTR_LTM_1_INTR, sde_cfg->mdss_irqs); Loading Loading @@ -4255,7 +4239,6 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) sde_cfg->has_decimation = true; sde_cfg->sui_block_xin_mask = 0x2EE1; sde_cfg->has_sui_blendstage = true; sde_cfg->has_qos_fl_nocalc = true; sde_cfg->has_3d_merge_reset = true; clear_bit(MDSS_INTR_LTM_0_INTR, sde_cfg->mdss_irqs); clear_bit(MDSS_INTR_LTM_1_INTR, sde_cfg->mdss_irqs); Loading @@ -4274,7 +4257,6 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) sde_cfg->sui_misr_supported = true; sde_cfg->sui_block_xin_mask = 0xE71; sde_cfg->has_sui_blendstage = true; sde_cfg->has_qos_fl_nocalc = true; sde_cfg->has_3d_merge_reset = true; } else if (IS_KONA_TARGET(hw_rev)) { sde_cfg->has_cwb_support = true; Loading @@ -4289,7 +4271,6 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) sde_cfg->sui_misr_supported = true; sde_cfg->sui_block_xin_mask = 0x3F71; sde_cfg->has_sui_blendstage = true; sde_cfg->has_qos_fl_nocalc = true; sde_cfg->has_3d_merge_reset = true; clear_bit(MDSS_INTR_AD4_0_INTR, sde_cfg->mdss_irqs); clear_bit(MDSS_INTR_AD4_1_INTR, sde_cfg->mdss_irqs); Loading @@ -4312,7 +4293,6 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) sde_cfg->sui_misr_supported = true; sde_cfg->sui_block_xin_mask = 0xE71; sde_cfg->has_sui_blendstage = true; sde_cfg->has_qos_fl_nocalc = true; sde_cfg->has_3d_merge_reset = true; clear_bit(MDSS_INTR_AD4_0_INTR, sde_cfg->mdss_irqs); clear_bit(MDSS_INTR_AD4_1_INTR, sde_cfg->mdss_irqs); Loading Loading @@ -4348,7 +4328,6 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) sde_cfg->sui_block_xin_mask = 0xC01; sde_cfg->has_hdr = false; sde_cfg->has_sui_blendstage = true; sde_cfg->has_qos_fl_nocalc = true; clear_bit(MDSS_INTR_AD4_0_INTR, sde_cfg->mdss_irqs); clear_bit(MDSS_INTR_AD4_1_INTR, sde_cfg->mdss_irqs); } else if (IS_LAGOON_TARGET(hw_rev)) { Loading @@ -4363,7 +4342,6 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) sde_cfg->sui_misr_supported = true; sde_cfg->sui_block_xin_mask = 0x261; sde_cfg->has_sui_blendstage = true; sde_cfg->has_qos_fl_nocalc = true; clear_bit(MDSS_INTR_AD4_0_INTR, sde_cfg->mdss_irqs); clear_bit(MDSS_INTR_AD4_1_INTR, sde_cfg->mdss_irqs); sde_cfg->has_hdr = true; Loading Loading @@ -4403,10 +4381,6 @@ static int _sde_hardware_post_caps(struct sde_mdss_cfg *sde_cfg, sde_cfg->sspp[i].sblk->maxvdeciexp); } if (sde_cfg->has_qos_fl_nocalc) set_bit(SDE_PERF_SSPP_QOS_FL_NOCALC, &sde_cfg->sspp[i].perf_features); /* * set sec-ui blocked SSPP feature flag based on blocked * xin-mask if sec-ui-misr feature is enabled; Loading Loading @@ -4489,10 +4463,10 @@ void sde_hw_catalog_deinit(struct sde_mdss_cfg *sde_cfg) kfree(sde_cfg->limit_cfg[i].value_cfg); } for (i = 0; i < SDE_QOS_LUT_USAGE_MAX; i++) { kfree(sde_cfg->perf.sfe_lut_tbl[i].entries); kfree(sde_cfg->perf.qos_lut_tbl[i].entries); } kfree(sde_cfg->perf.qos_refresh_rate); kfree(sde_cfg->perf.danger_lut); kfree(sde_cfg->perf.safe_lut); kfree(sde_cfg->perf.creq_lut); kfree(sde_cfg->dma_formats); kfree(sde_cfg->cursor_formats); Loading Loading @@ -4531,6 +4505,10 @@ struct sde_mdss_cfg *sde_hw_catalog_init(struct drm_device *dev, u32 hw_rev) if (rc) goto end; rc = sde_qos_parse_dt(np, sde_cfg); if (rc) goto end; rc = sde_rot_parse_dt(np, sde_cfg); if (rc) goto end; Loading msm/sde/sde_hw_catalog.h +10 −30 Original line number Diff line number Diff line Loading @@ -260,7 +260,6 @@ enum { * @SDE_PERF_SSPP_TS_PREFILL Supports prefill with traffic shaper * @SDE_PERF_SSPP_TS_PREFILL_REC1 Supports prefill with traffic shaper multirec * @SDE_PERF_SSPP_CDP Supports client driven prefetch * @SDE_PERF_SSPP_QOS_FL_NOCALC Avoid fill level calc for QoS/danger/safe * @SDE_PERF_SSPP_SYS_CACHE, SSPP supports system cache * @SDE_PERF_SSPP_UIDLE, sspp supports uidle * @SDE_PERF_SSPP_MAX Maximum value Loading @@ -271,7 +270,6 @@ enum { SDE_PERF_SSPP_TS_PREFILL, SDE_PERF_SSPP_TS_PREFILL_REC1, SDE_PERF_SSPP_CDP, SDE_PERF_SSPP_QOS_FL_NOCALC, SDE_PERF_SSPP_SYS_CACHE, SDE_PERF_SSPP_UIDLE, SDE_PERF_SSPP_MAX Loading Loading @@ -568,26 +566,6 @@ enum sde_qos_lut_usage { SDE_QOS_LUT_USAGE_MAX, }; /** * struct sde_qos_lut_entry - define QoS LUT table entry * @fl: fill level, or zero on last entry to indicate default lut * @lut: lut to use if equal to or less than fill level */ struct sde_qos_lut_entry { u32 fl; u64 lut; }; /** * struct sde_qos_lut_tbl - define QoS LUT table * @nentry: number of entry in this table * @entries: Pointer to table entries */ struct sde_qos_lut_tbl { u32 nentry; struct sde_qos_lut_entry *entries; }; /** * struct sde_sspp_sub_blks : SSPP sub-blocks * @maxdwnscale: max downscale ratio supported(without DECIMATION) Loading Loading @@ -1154,9 +1132,11 @@ struct sde_sc_cfg { * @downscaling_prefill_lines downscaling latency in lines * @amortizable_theshold minimum y position for traffic shaping prefill * @min_prefill_lines minimum pipeline latency in lines * @danger_lut_tbl: LUT tables for danger signals * @sfe_lut_tbl: LUT tables for safe signals * @qos_lut_tbl: LUT tables for QoS signals * @danger_lut: linear, macrotile, etc. danger luts * @safe_lut: linear, macrotile, macrotile_qseed, etc. safe luts * @creq_lut: linear, macrotile, non_realtime, cwb, etc. creq luts * @qos_refresh_count: total refresh count for possible different luts * @qos_refresh_rate: different refresh rates for luts * @cdp_cfg cdp use case configurations * @cpu_mask: pm_qos cpu mask value * @cpu_dma_latency: pm_qos cpu dma latency value Loading @@ -1182,9 +1162,11 @@ struct sde_perf_cfg { u32 downscaling_prefill_lines; u32 amortizable_threshold; u32 min_prefill_lines; u32 danger_lut_tbl[SDE_QOS_LUT_USAGE_MAX]; struct sde_qos_lut_tbl sfe_lut_tbl[SDE_QOS_LUT_USAGE_MAX]; struct sde_qos_lut_tbl qos_lut_tbl[SDE_QOS_LUT_USAGE_MAX]; u64 *danger_lut; u64 *safe_lut; u64 *creq_lut; u32 qos_refresh_count; u32 *qos_refresh_rate; struct sde_perf_cdp_cfg cdp_cfg[SDE_PERF_CDP_USAGE_MAX]; u32 cpu_mask; u32 cpu_dma_latency; Loading Loading @@ -1276,7 +1258,6 @@ struct sde_limit_cfg { * @has_qsync Supports qsync feature * @has_3d_merge_reset Supports 3D merge reset * @has_decimation Supports decimation * @has_qos_fl_nocalc flag to indicate QoS fill level needs no calculation * @update_tcsr_disp_glitch flag to enable HW workaround to avoid spurious * transactions during suspend * @has_base_layer Supports staging layer as base layer Loading Loading @@ -1335,7 +1316,6 @@ struct sde_mdss_cfg { bool has_qsync; bool has_3d_merge_reset; bool has_decimation; bool has_qos_fl_nocalc; bool update_tcsr_disp_glitch; bool has_base_layer; Loading msm/sde/sde_hw_sspp.c +3 −13 Original line number Diff line number Diff line Loading @@ -844,7 +844,7 @@ static void sde_hw_sspp_setup_solidfill(struct sde_hw_pipe *ctx, u32 color, enum color); } static void sde_hw_sspp_setup_danger_safe_lut(struct sde_hw_pipe *ctx, static void sde_hw_sspp_setup_qos_lut(struct sde_hw_pipe *ctx, struct sde_hw_pipe_qos_cfg *cfg) { u32 idx; Loading @@ -854,15 +854,6 @@ static void sde_hw_sspp_setup_danger_safe_lut(struct sde_hw_pipe *ctx, SDE_REG_WRITE(&ctx->hw, SSPP_DANGER_LUT + idx, cfg->danger_lut); SDE_REG_WRITE(&ctx->hw, SSPP_SAFE_LUT + idx, cfg->safe_lut); } static void sde_hw_sspp_setup_creq_lut(struct sde_hw_pipe *ctx, struct sde_hw_pipe_qos_cfg *cfg) { u32 idx; if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx)) return; if (ctx->cap && test_bit(SDE_PERF_SSPP_QOS_8LVL, &ctx->cap->perf_features)) { Loading Loading @@ -1224,9 +1215,8 @@ static void _setup_layer_ops(struct sde_hw_pipe *c, c->ops.setup_excl_rect = _sde_hw_sspp_setup_excl_rect; if (test_bit(SDE_PERF_SSPP_QOS, &features)) { c->ops.setup_danger_safe_lut = sde_hw_sspp_setup_danger_safe_lut; c->ops.setup_creq_lut = sde_hw_sspp_setup_creq_lut; c->ops.setup_qos_lut = sde_hw_sspp_setup_qos_lut; c->ops.setup_qos_ctrl = sde_hw_sspp_setup_qos_ctrl; } Loading msm/sde/sde_hw_sspp.h +2 −11 Original line number Diff line number Diff line Loading @@ -460,21 +460,12 @@ struct sde_hw_sspp_ops { enum sde_sspp_multirect_index idx); /** * setup_danger_safe_lut - setup danger safe LUTs * setup_qos_lut - setup danger, safe, creq LUTs * @ctx: Pointer to pipe context * @cfg: Pointer to pipe QoS configuration * */ void (*setup_danger_safe_lut)(struct sde_hw_pipe *ctx, struct sde_hw_pipe_qos_cfg *cfg); /** * setup_creq_lut - setup CREQ LUT * @ctx: Pointer to pipe context * @cfg: Pointer to pipe QoS configuration * */ void (*setup_creq_lut)(struct sde_hw_pipe *ctx, void (*setup_qos_lut)(struct sde_hw_pipe *ctx, struct sde_hw_pipe_qos_cfg *cfg); /** Loading Loading
msm/sde/sde_encoder_phys_wb.c +27 −43 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ Loading Loading @@ -136,25 +136,6 @@ static void sde_encoder_phys_wb_set_qos_remap( sde_vbif_set_qos_remap(phys_enc->sde_kms, &qos_params); } static u64 _sde_encoder_phys_wb_get_qos_lut(const struct sde_qos_lut_tbl *tbl, u32 total_fl) { int i; if (!tbl || !tbl->nentry || !tbl->entries) return 0; for (i = 0; i < tbl->nentry; i++) if (total_fl <= tbl->entries[i].fl) return tbl->entries[i].lut; /* if last fl is zero, use as default */ if (!tbl->entries[i-1].fl) return tbl->entries[i-1].lut; return 0; } /** * sde_encoder_phys_wb_set_qos - set QoS/danger/safe LUTs for writeback * @phys_enc: Pointer to physical encoder Loading @@ -163,14 +144,14 @@ static void sde_encoder_phys_wb_set_qos(struct sde_encoder_phys *phys_enc) { struct sde_encoder_phys_wb *wb_enc; struct sde_hw_wb *hw_wb; struct sde_hw_wb_qos_cfg qos_cfg; struct sde_mdss_cfg *catalog; struct sde_hw_wb_qos_cfg qos_cfg = {0}; struct sde_perf_cfg *perf; u32 fps_index = 0, lut_index, index, frame_rate, qos_count; if (!phys_enc || !phys_enc->sde_kms || !phys_enc->sde_kms->catalog) { SDE_ERROR("invalid parameter(s)\n"); return; } catalog = phys_enc->sde_kms->catalog; wb_enc = to_sde_encoder_phys_wb(phys_enc); if (!wb_enc->hw_wb) { Loading @@ -178,35 +159,38 @@ static void sde_encoder_phys_wb_set_qos(struct sde_encoder_phys *phys_enc) return; } perf = &phys_enc->sde_kms->catalog->perf; frame_rate = phys_enc->cached_mode.vrefresh; hw_wb = wb_enc->hw_wb; qos_count = perf->qos_refresh_count; while (qos_count && perf->qos_refresh_rate) { if (frame_rate >= perf->qos_refresh_rate[qos_count - 1]) { fps_index = qos_count - 1; break; } qos_count--; } memset(&qos_cfg, 0, sizeof(struct sde_hw_wb_qos_cfg)); qos_cfg.danger_safe_en = true; qos_cfg.danger_lut = catalog->perf.danger_lut_tbl[SDE_QOS_LUT_USAGE_NRT]; if (phys_enc->in_clone_mode) qos_cfg.safe_lut = (u32) _sde_encoder_phys_wb_get_qos_lut( &catalog->perf.sfe_lut_tbl[SDE_QOS_LUT_USAGE_CWB], 0); else qos_cfg.safe_lut = (u32) _sde_encoder_phys_wb_get_qos_lut( &catalog->perf.sfe_lut_tbl[SDE_QOS_LUT_USAGE_NRT], 0); if (phys_enc->in_clone_mode) qos_cfg.creq_lut = _sde_encoder_phys_wb_get_qos_lut( &catalog->perf.qos_lut_tbl[SDE_QOS_LUT_USAGE_CWB], 0); lut_index = SDE_QOS_LUT_USAGE_CWB; else qos_cfg.creq_lut = _sde_encoder_phys_wb_get_qos_lut( &catalog->perf.qos_lut_tbl[SDE_QOS_LUT_USAGE_NRT], 0); lut_index = SDE_QOS_LUT_USAGE_NRT; index = (fps_index * SDE_QOS_LUT_USAGE_MAX) + lut_index; if (hw_wb->ops.setup_danger_safe_lut) hw_wb->ops.setup_danger_safe_lut(hw_wb, &qos_cfg); qos_cfg.danger_lut = perf->danger_lut[index]; qos_cfg.safe_lut = (u32) perf->safe_lut[index]; qos_cfg.creq_lut = perf->creq_lut[index]; if (hw_wb->ops.setup_creq_lut) hw_wb->ops.setup_creq_lut(hw_wb, &qos_cfg); SDE_DEBUG("wb_enc:%d hw idx:%d fps:%d mode:%d luts[0x%x,0x%x 0x%llx]\n", DRMID(phys_enc->parent), hw_wb->idx - WB_0, frame_rate, phys_enc->in_clone_mode, qos_cfg.danger_lut, qos_cfg.safe_lut, qos_cfg.creq_lut); if (hw_wb->ops.setup_qos_ctrl) hw_wb->ops.setup_qos_ctrl(hw_wb, &qos_cfg); if (hw_wb->ops.setup_qos_lut) hw_wb->ops.setup_qos_lut(hw_wb, &qos_cfg); } /** Loading
msm/sde/sde_hw_catalog.c +162 −184 Original line number Diff line number Diff line Loading @@ -218,25 +218,30 @@ enum { PERF_DOWNSCALING_PREFILL_LINES, PERF_XTRA_PREFILL_LINES, PERF_AMORTIZABLE_THRESHOLD, PERF_DANGER_LUT, PERF_SAFE_LUT_LINEAR, PERF_SAFE_LUT_MACROTILE, PERF_SAFE_LUT_NRT, PERF_SAFE_LUT_CWB, PERF_QOS_LUT_LINEAR, PERF_QOS_LUT_MACROTILE, PERF_QOS_LUT_NRT, PERF_QOS_LUT_CWB, PERF_NUM_MNOC_PORTS, PERF_AXI_BUS_WIDTH, PERF_CDP_SETTING, PERF_CPU_MASK, PERF_CPU_DMA_LATENCY, PERF_QOS_LUT_MACROTILE_QSEED, PERF_SAFE_LUT_MACROTILE_QSEED, PERF_NUM_MNOC_PORTS, PERF_AXI_BUS_WIDTH, PERF_PROP_MAX, }; enum { QOS_REFRESH_RATES, QOS_DANGER_LUT, QOS_SAFE_LUT_LINEAR, QOS_SAFE_LUT_MACROTILE, QOS_SAFE_LUT_NRT, QOS_SAFE_LUT_CWB, QOS_SAFE_LUT_MACROTILE_QSEED, QOS_CREQ_LUT_LINEAR, QOS_CREQ_LUT_MACROTILE, QOS_CREQ_LUT_NRT, QOS_CREQ_LUT_CWB, QOS_CREQ_LUT_MACROTILE_QSEED, QOS_PROP_MAX, }; enum { SSPP_OFF, SSPP_SIZE, Loading Loading @@ -532,37 +537,41 @@ static struct sde_prop_type sde_perf_prop[] = { false, PROP_TYPE_U32}, {PERF_AMORTIZABLE_THRESHOLD, "qcom,sde-amortizable-threshold", false, PROP_TYPE_U32}, {PERF_DANGER_LUT, "qcom,sde-danger-lut", false, PROP_TYPE_U32_ARRAY}, {PERF_SAFE_LUT_LINEAR, "qcom,sde-safe-lut-linear", false, {PERF_NUM_MNOC_PORTS, "qcom,sde-num-mnoc-ports", false, PROP_TYPE_U32}, {PERF_AXI_BUS_WIDTH, "qcom,sde-axi-bus-width", false, PROP_TYPE_U32}, {PERF_CDP_SETTING, "qcom,sde-cdp-setting", false, PROP_TYPE_U32_ARRAY}, {PERF_SAFE_LUT_MACROTILE, "qcom,sde-safe-lut-macrotile", false, {PERF_CPU_MASK, "qcom,sde-qos-cpu-mask", false, PROP_TYPE_U32}, {PERF_CPU_DMA_LATENCY, "qcom,sde-qos-cpu-dma-latency", false, PROP_TYPE_U32}, }; static struct sde_prop_type sde_qos_prop[] = { {QOS_REFRESH_RATES, "qcom,sde-qos-refresh-rates", false, PROP_TYPE_U32_ARRAY}, {QOS_DANGER_LUT, "qcom,sde-danger-lut", false, PROP_TYPE_U32_ARRAY}, {QOS_SAFE_LUT_LINEAR, "qcom,sde-safe-lut-linear", false, PROP_TYPE_U32_ARRAY}, {PERF_SAFE_LUT_NRT, "qcom,sde-safe-lut-nrt", false, {QOS_SAFE_LUT_MACROTILE, "qcom,sde-safe-lut-macrotile", false, PROP_TYPE_U32_ARRAY}, {PERF_SAFE_LUT_CWB, "qcom,sde-safe-lut-cwb", false, {QOS_SAFE_LUT_NRT, "qcom,sde-safe-lut-nrt", false, PROP_TYPE_U32_ARRAY}, {PERF_QOS_LUT_LINEAR, "qcom,sde-qos-lut-linear", false, {QOS_SAFE_LUT_CWB, "qcom,sde-safe-lut-cwb", false, PROP_TYPE_U32_ARRAY}, {PERF_QOS_LUT_MACROTILE, "qcom,sde-qos-lut-macrotile", false, {QOS_SAFE_LUT_MACROTILE_QSEED, "qcom,sde-safe-lut-macrotile-qseed", false, PROP_TYPE_U32_ARRAY}, {QOS_CREQ_LUT_LINEAR, "qcom,sde-qos-lut-linear", false, PROP_TYPE_U32_ARRAY}, {PERF_QOS_LUT_NRT, "qcom,sde-qos-lut-nrt", false, {QOS_CREQ_LUT_MACROTILE, "qcom,sde-qos-lut-macrotile", false, PROP_TYPE_U32_ARRAY}, {PERF_QOS_LUT_CWB, "qcom,sde-qos-lut-cwb", false, {QOS_CREQ_LUT_NRT, "qcom,sde-qos-lut-nrt", false, PROP_TYPE_U32_ARRAY}, {PERF_CDP_SETTING, "qcom,sde-cdp-setting", false, {QOS_CREQ_LUT_CWB, "qcom,sde-qos-lut-cwb", false, PROP_TYPE_U32_ARRAY}, {PERF_CPU_MASK, "qcom,sde-qos-cpu-mask", false, PROP_TYPE_U32}, {PERF_CPU_DMA_LATENCY, "qcom,sde-qos-cpu-dma-latency", false, PROP_TYPE_U32}, {PERF_QOS_LUT_MACROTILE_QSEED, "qcom,sde-qos-lut-macrotile-qseed", false, PROP_TYPE_U32_ARRAY}, {PERF_SAFE_LUT_MACROTILE_QSEED, "qcom,sde-safe-lut-macrotile-qseed", {QOS_CREQ_LUT_MACROTILE_QSEED, "qcom,sde-qos-lut-macrotile-qseed", false, PROP_TYPE_U32_ARRAY}, {PERF_NUM_MNOC_PORTS, "qcom,sde-num-mnoc-ports", false, PROP_TYPE_U32}, {PERF_AXI_BUS_WIDTH, "qcom,sde-axi-bus-width", false, PROP_TYPE_U32}, }; static struct sde_prop_type sspp_prop[] = { Loading Loading @@ -3580,172 +3589,116 @@ static int _sde_perf_parse_dt_validate(struct device_node *np, int *prop_count) if (rc) return rc; rc = _validate_dt_entry(np, &sde_perf_prop[PERF_DANGER_LUT], 1, &prop_count[PERF_DANGER_LUT], NULL); if (rc) return rc; rc = _validate_dt_entry(np, &sde_perf_prop[PERF_SAFE_LUT_LINEAR], 1, &prop_count[PERF_SAFE_LUT_LINEAR], NULL); if (rc) return rc; rc = _validate_dt_entry(np, &sde_perf_prop[PERF_SAFE_LUT_MACROTILE], 1, &prop_count[PERF_SAFE_LUT_MACROTILE], NULL); if (rc) return rc; rc = _validate_dt_entry(np, &sde_perf_prop[PERF_SAFE_LUT_NRT], 1, &prop_count[PERF_SAFE_LUT_NRT], NULL); if (rc) return rc; rc = _validate_dt_entry(np, &sde_perf_prop[PERF_SAFE_LUT_CWB], 1, &prop_count[PERF_SAFE_LUT_CWB], NULL); if (rc) return rc; rc = _validate_dt_entry(np, &sde_perf_prop[PERF_QOS_LUT_LINEAR], 1, &prop_count[PERF_QOS_LUT_LINEAR], NULL); if (rc) return rc; rc = _validate_dt_entry(np, &sde_perf_prop[PERF_QOS_LUT_MACROTILE], 1, &prop_count[PERF_QOS_LUT_MACROTILE], NULL); if (rc) return rc; rc = _validate_dt_entry(np, &sde_perf_prop[PERF_QOS_LUT_NRT], 1, &prop_count[PERF_QOS_LUT_NRT], NULL); if (rc) return rc; rc = _validate_dt_entry(np, &sde_perf_prop[PERF_QOS_LUT_CWB], 1, &prop_count[PERF_QOS_LUT_CWB], NULL); if (rc) return rc; rc = _validate_dt_entry(np, &sde_perf_prop[PERF_CDP_SETTING], 1, &prop_count[PERF_CDP_SETTING], NULL); if (rc) return rc; rc = _validate_dt_entry(np, &sde_perf_prop[PERF_QOS_LUT_MACROTILE_QSEED], 1, &prop_count[PERF_QOS_LUT_MACROTILE_QSEED], NULL); if (rc) return rc; rc = _validate_dt_entry(np, &sde_perf_prop[PERF_SAFE_LUT_MACROTILE_QSEED], 1, &prop_count[PERF_SAFE_LUT_MACROTILE_QSEED], NULL); return rc; } static int _sde_perf_parse_dt_cfg_qos(struct sde_mdss_cfg *cfg, int *prop_count, static int _sde_qos_parse_dt_cfg(struct sde_mdss_cfg *cfg, int *prop_count, struct sde_prop_value *prop_value, bool *prop_exists) { int j, k; int i, j; u32 qos_count = 1, index; if (prop_exists[PERF_DANGER_LUT] && prop_count[PERF_DANGER_LUT] <= SDE_QOS_LUT_USAGE_MAX) { for (j = 0; j < prop_count[PERF_DANGER_LUT]; j++) { cfg->perf.danger_lut_tbl[j] = if (prop_exists[QOS_REFRESH_RATES]) { qos_count = prop_count[QOS_REFRESH_RATES]; cfg->perf.qos_refresh_rate = kcalloc(qos_count, sizeof(u32), GFP_KERNEL); if (!cfg->perf.qos_refresh_rate) goto end; for (j = 0; j < qos_count; j++) { cfg->perf.qos_refresh_rate[j] = PROP_VALUE_ACCESS(prop_value, PERF_DANGER_LUT, j); SDE_DEBUG("danger usage:%d lut:0x%x\n", j, cfg->perf.danger_lut_tbl[j]); QOS_REFRESH_RATES, j); SDE_DEBUG("qos usage:%d refresh rate:0x%x\n", j, cfg->perf.qos_refresh_rate[j]); } } cfg->perf.qos_refresh_count = qos_count; for (j = 0; j < SDE_QOS_LUT_USAGE_MAX; j++) { static const u32 safe_key[SDE_QOS_LUT_USAGE_MAX] = { cfg->perf.danger_lut = kcalloc(qos_count, sizeof(u64) * SDE_QOS_LUT_USAGE_MAX, GFP_KERNEL); cfg->perf.safe_lut = kcalloc(qos_count, sizeof(u64) * SDE_QOS_LUT_USAGE_MAX, GFP_KERNEL); cfg->perf.creq_lut = kcalloc(qos_count, sizeof(u64) * SDE_QOS_LUT_USAGE_MAX, GFP_KERNEL); if (!cfg->perf.creq_lut || !cfg->perf.safe_lut || !cfg->perf.danger_lut) goto end; if (prop_exists[QOS_DANGER_LUT] && prop_count[QOS_DANGER_LUT] >= (SDE_QOS_LUT_USAGE_MAX * qos_count)) { for (i = 0; i < prop_count[QOS_DANGER_LUT]; i++) { cfg->perf.danger_lut[i] = PROP_VALUE_ACCESS(prop_value, QOS_DANGER_LUT, i); SDE_DEBUG("danger usage:%i lut:0x%x\n", i, cfg->perf.danger_lut[i]); } } for (i = 0; i < SDE_QOS_LUT_USAGE_MAX; i++) { static const u32 prop_creq_key[SDE_QOS_LUT_USAGE_MAX] = { [SDE_QOS_LUT_USAGE_LINEAR] = PERF_SAFE_LUT_LINEAR, QOS_CREQ_LUT_LINEAR, [SDE_QOS_LUT_USAGE_MACROTILE] = PERF_SAFE_LUT_MACROTILE, QOS_CREQ_LUT_MACROTILE, [SDE_QOS_LUT_USAGE_NRT] = PERF_SAFE_LUT_NRT, QOS_CREQ_LUT_NRT, [SDE_QOS_LUT_USAGE_CWB] = PERF_SAFE_LUT_CWB, QOS_CREQ_LUT_CWB, [SDE_QOS_LUT_USAGE_MACROTILE_QSEED] = PERF_SAFE_LUT_MACROTILE_QSEED, QOS_CREQ_LUT_MACROTILE_QSEED, }; const u32 entry_size = 2; int m, count; int key = safe_key[j]; if (!prop_exists[key]) continue; count = prop_count[key] / entry_size; cfg->perf.sfe_lut_tbl[j].entries = kcalloc(count, sizeof(struct sde_qos_lut_entry), GFP_KERNEL); if (!cfg->perf.sfe_lut_tbl[j].entries) return -ENOMEM; for (k = 0, m = 0; k < count; k++, m += entry_size) { u64 lut_lo; cfg->perf.sfe_lut_tbl[j].entries[k].fl = PROP_VALUE_ACCESS(prop_value, key, m); lut_lo = PROP_VALUE_ACCESS(prop_value, key, m + 1); cfg->perf.sfe_lut_tbl[j].entries[k].lut = lut_lo; SDE_DEBUG("safe usage:%d.%d fl:%d lut:0x%llx\n", j, k, cfg->perf.sfe_lut_tbl[j].entries[k].fl, cfg->perf.sfe_lut_tbl[j].entries[k].lut); } cfg->perf.sfe_lut_tbl[j].nentry = count; } for (j = 0; j < SDE_QOS_LUT_USAGE_MAX; j++) { static const u32 prop_key[SDE_QOS_LUT_USAGE_MAX] = { static const u32 prop_safe_key[SDE_QOS_LUT_USAGE_MAX] = { [SDE_QOS_LUT_USAGE_LINEAR] = PERF_QOS_LUT_LINEAR, QOS_SAFE_LUT_LINEAR, [SDE_QOS_LUT_USAGE_MACROTILE] = PERF_QOS_LUT_MACROTILE, QOS_SAFE_LUT_MACROTILE, [SDE_QOS_LUT_USAGE_NRT] = PERF_QOS_LUT_NRT, QOS_SAFE_LUT_NRT, [SDE_QOS_LUT_USAGE_CWB] = PERF_QOS_LUT_CWB, QOS_SAFE_LUT_CWB, [SDE_QOS_LUT_USAGE_MACROTILE_QSEED] = PERF_QOS_LUT_MACROTILE_QSEED, QOS_SAFE_LUT_MACROTILE_QSEED, }; const u32 entry_size = 3; int m, count; int key = prop_key[j]; int creq_key = prop_creq_key[i]; int safe_key = prop_safe_key[i]; u64 lut_hi, lut_lo; if (!prop_exists[key]) if (!prop_exists[creq_key] || !prop_exists[safe_key]) continue; count = prop_count[key] / entry_size; for (j = 0; j < qos_count; j++) { lut_hi = PROP_VALUE_ACCESS(prop_value, creq_key, (j * 3) + 1); lut_lo = PROP_VALUE_ACCESS(prop_value, creq_key, (j * 3) + 2); index = (j * SDE_QOS_LUT_USAGE_MAX) + i; cfg->perf.qos_lut_tbl[j].entries = kcalloc(count, sizeof(struct sde_qos_lut_entry), GFP_KERNEL); if (!cfg->perf.qos_lut_tbl[j].entries) return -ENOMEM; for (k = 0, m = 0; k < count; k++, m += entry_size) { u64 lut_hi, lut_lo; cfg->perf.qos_lut_tbl[j].entries[k].fl = PROP_VALUE_ACCESS(prop_value, key, m); lut_hi = PROP_VALUE_ACCESS(prop_value, key, m + 1); lut_lo = PROP_VALUE_ACCESS(prop_value, key, m + 2); cfg->perf.qos_lut_tbl[j].entries[k].lut = cfg->perf.creq_lut[index] = (lut_hi << 32) | lut_lo; SDE_DEBUG("usage:%d.%d fl:%d lut:0x%llx\n", j, k, cfg->perf.qos_lut_tbl[j].entries[k].fl, cfg->perf.qos_lut_tbl[j].entries[k].lut); cfg->perf.safe_lut[index] = PROP_VALUE_ACCESS(prop_value, safe_key, (j * 2) + 1); SDE_DEBUG("usage:%d creq lut:0x%llx safe:0x%x\n", index, cfg->perf.creq_lut[index], cfg->perf.safe_lut[index]); } cfg->perf.qos_lut_tbl[j].nentry = count; } return 0; end: kfree(cfg->perf.qos_refresh_rate); kfree(cfg->perf.creq_lut); kfree(cfg->perf.danger_lut); kfree(cfg->perf.safe_lut); return -ENOMEM; } static void _sde_perf_parse_dt_cfg_populate(struct sde_mdss_cfg *cfg, Loading Loading @@ -3854,11 +3807,6 @@ static int _sde_perf_parse_dt_cfg(struct device_node *np, _sde_perf_parse_dt_cfg_populate(cfg, prop_count, prop_value, prop_exists); rc = _sde_perf_parse_dt_cfg_qos(cfg, prop_count, prop_value, prop_exists); if (rc) return rc; if (prop_exists[PERF_CDP_SETTING]) { const u32 prop_size = 2; u32 count = prop_count[PERF_CDP_SETTING] / prop_size; Loading Loading @@ -3929,6 +3877,43 @@ static int sde_perf_parse_dt(struct device_node *np, struct sde_mdss_cfg *cfg) return rc; } static int sde_qos_parse_dt(struct device_node *np, struct sde_mdss_cfg *cfg) { int rc, prop_count[QOS_PROP_MAX]; struct sde_prop_value *prop_value = NULL; bool prop_exists[QOS_PROP_MAX]; if (!cfg) { SDE_ERROR("invalid argument\n"); rc = -EINVAL; goto end; } prop_value = kzalloc(QOS_PROP_MAX * sizeof(struct sde_prop_value), GFP_KERNEL); if (!prop_value) { rc = -ENOMEM; goto end; } rc = _validate_dt_entry(np, sde_qos_prop, ARRAY_SIZE(sde_qos_prop), prop_count, NULL); if (rc) goto freeprop; rc = _read_dt_entry(np, sde_qos_prop, ARRAY_SIZE(sde_qos_prop), prop_count, prop_exists, prop_value); if (rc) goto freeprop; rc = _sde_qos_parse_dt_cfg(cfg, prop_count, prop_value, prop_exists); freeprop: kfree(prop_value); end: return rc; } static int sde_parse_merge_3d_dt(struct device_node *np, struct sde_mdss_cfg *sde_cfg) { Loading Loading @@ -4225,7 +4210,6 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) sde_cfg->sui_misr_supported = true; sde_cfg->sui_block_xin_mask = 0x3F71; sde_cfg->has_sui_blendstage = true; sde_cfg->has_qos_fl_nocalc = true; sde_cfg->has_3d_merge_reset = true; clear_bit(MDSS_INTR_LTM_0_INTR, sde_cfg->mdss_irqs); clear_bit(MDSS_INTR_LTM_1_INTR, sde_cfg->mdss_irqs); Loading Loading @@ -4255,7 +4239,6 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) sde_cfg->has_decimation = true; sde_cfg->sui_block_xin_mask = 0x2EE1; sde_cfg->has_sui_blendstage = true; sde_cfg->has_qos_fl_nocalc = true; sde_cfg->has_3d_merge_reset = true; clear_bit(MDSS_INTR_LTM_0_INTR, sde_cfg->mdss_irqs); clear_bit(MDSS_INTR_LTM_1_INTR, sde_cfg->mdss_irqs); Loading @@ -4274,7 +4257,6 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) sde_cfg->sui_misr_supported = true; sde_cfg->sui_block_xin_mask = 0xE71; sde_cfg->has_sui_blendstage = true; sde_cfg->has_qos_fl_nocalc = true; sde_cfg->has_3d_merge_reset = true; } else if (IS_KONA_TARGET(hw_rev)) { sde_cfg->has_cwb_support = true; Loading @@ -4289,7 +4271,6 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) sde_cfg->sui_misr_supported = true; sde_cfg->sui_block_xin_mask = 0x3F71; sde_cfg->has_sui_blendstage = true; sde_cfg->has_qos_fl_nocalc = true; sde_cfg->has_3d_merge_reset = true; clear_bit(MDSS_INTR_AD4_0_INTR, sde_cfg->mdss_irqs); clear_bit(MDSS_INTR_AD4_1_INTR, sde_cfg->mdss_irqs); Loading @@ -4312,7 +4293,6 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) sde_cfg->sui_misr_supported = true; sde_cfg->sui_block_xin_mask = 0xE71; sde_cfg->has_sui_blendstage = true; sde_cfg->has_qos_fl_nocalc = true; sde_cfg->has_3d_merge_reset = true; clear_bit(MDSS_INTR_AD4_0_INTR, sde_cfg->mdss_irqs); clear_bit(MDSS_INTR_AD4_1_INTR, sde_cfg->mdss_irqs); Loading Loading @@ -4348,7 +4328,6 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) sde_cfg->sui_block_xin_mask = 0xC01; sde_cfg->has_hdr = false; sde_cfg->has_sui_blendstage = true; sde_cfg->has_qos_fl_nocalc = true; clear_bit(MDSS_INTR_AD4_0_INTR, sde_cfg->mdss_irqs); clear_bit(MDSS_INTR_AD4_1_INTR, sde_cfg->mdss_irqs); } else if (IS_LAGOON_TARGET(hw_rev)) { Loading @@ -4363,7 +4342,6 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) sde_cfg->sui_misr_supported = true; sde_cfg->sui_block_xin_mask = 0x261; sde_cfg->has_sui_blendstage = true; sde_cfg->has_qos_fl_nocalc = true; clear_bit(MDSS_INTR_AD4_0_INTR, sde_cfg->mdss_irqs); clear_bit(MDSS_INTR_AD4_1_INTR, sde_cfg->mdss_irqs); sde_cfg->has_hdr = true; Loading Loading @@ -4403,10 +4381,6 @@ static int _sde_hardware_post_caps(struct sde_mdss_cfg *sde_cfg, sde_cfg->sspp[i].sblk->maxvdeciexp); } if (sde_cfg->has_qos_fl_nocalc) set_bit(SDE_PERF_SSPP_QOS_FL_NOCALC, &sde_cfg->sspp[i].perf_features); /* * set sec-ui blocked SSPP feature flag based on blocked * xin-mask if sec-ui-misr feature is enabled; Loading Loading @@ -4489,10 +4463,10 @@ void sde_hw_catalog_deinit(struct sde_mdss_cfg *sde_cfg) kfree(sde_cfg->limit_cfg[i].value_cfg); } for (i = 0; i < SDE_QOS_LUT_USAGE_MAX; i++) { kfree(sde_cfg->perf.sfe_lut_tbl[i].entries); kfree(sde_cfg->perf.qos_lut_tbl[i].entries); } kfree(sde_cfg->perf.qos_refresh_rate); kfree(sde_cfg->perf.danger_lut); kfree(sde_cfg->perf.safe_lut); kfree(sde_cfg->perf.creq_lut); kfree(sde_cfg->dma_formats); kfree(sde_cfg->cursor_formats); Loading Loading @@ -4531,6 +4505,10 @@ struct sde_mdss_cfg *sde_hw_catalog_init(struct drm_device *dev, u32 hw_rev) if (rc) goto end; rc = sde_qos_parse_dt(np, sde_cfg); if (rc) goto end; rc = sde_rot_parse_dt(np, sde_cfg); if (rc) goto end; Loading
msm/sde/sde_hw_catalog.h +10 −30 Original line number Diff line number Diff line Loading @@ -260,7 +260,6 @@ enum { * @SDE_PERF_SSPP_TS_PREFILL Supports prefill with traffic shaper * @SDE_PERF_SSPP_TS_PREFILL_REC1 Supports prefill with traffic shaper multirec * @SDE_PERF_SSPP_CDP Supports client driven prefetch * @SDE_PERF_SSPP_QOS_FL_NOCALC Avoid fill level calc for QoS/danger/safe * @SDE_PERF_SSPP_SYS_CACHE, SSPP supports system cache * @SDE_PERF_SSPP_UIDLE, sspp supports uidle * @SDE_PERF_SSPP_MAX Maximum value Loading @@ -271,7 +270,6 @@ enum { SDE_PERF_SSPP_TS_PREFILL, SDE_PERF_SSPP_TS_PREFILL_REC1, SDE_PERF_SSPP_CDP, SDE_PERF_SSPP_QOS_FL_NOCALC, SDE_PERF_SSPP_SYS_CACHE, SDE_PERF_SSPP_UIDLE, SDE_PERF_SSPP_MAX Loading Loading @@ -568,26 +566,6 @@ enum sde_qos_lut_usage { SDE_QOS_LUT_USAGE_MAX, }; /** * struct sde_qos_lut_entry - define QoS LUT table entry * @fl: fill level, or zero on last entry to indicate default lut * @lut: lut to use if equal to or less than fill level */ struct sde_qos_lut_entry { u32 fl; u64 lut; }; /** * struct sde_qos_lut_tbl - define QoS LUT table * @nentry: number of entry in this table * @entries: Pointer to table entries */ struct sde_qos_lut_tbl { u32 nentry; struct sde_qos_lut_entry *entries; }; /** * struct sde_sspp_sub_blks : SSPP sub-blocks * @maxdwnscale: max downscale ratio supported(without DECIMATION) Loading Loading @@ -1154,9 +1132,11 @@ struct sde_sc_cfg { * @downscaling_prefill_lines downscaling latency in lines * @amortizable_theshold minimum y position for traffic shaping prefill * @min_prefill_lines minimum pipeline latency in lines * @danger_lut_tbl: LUT tables for danger signals * @sfe_lut_tbl: LUT tables for safe signals * @qos_lut_tbl: LUT tables for QoS signals * @danger_lut: linear, macrotile, etc. danger luts * @safe_lut: linear, macrotile, macrotile_qseed, etc. safe luts * @creq_lut: linear, macrotile, non_realtime, cwb, etc. creq luts * @qos_refresh_count: total refresh count for possible different luts * @qos_refresh_rate: different refresh rates for luts * @cdp_cfg cdp use case configurations * @cpu_mask: pm_qos cpu mask value * @cpu_dma_latency: pm_qos cpu dma latency value Loading @@ -1182,9 +1162,11 @@ struct sde_perf_cfg { u32 downscaling_prefill_lines; u32 amortizable_threshold; u32 min_prefill_lines; u32 danger_lut_tbl[SDE_QOS_LUT_USAGE_MAX]; struct sde_qos_lut_tbl sfe_lut_tbl[SDE_QOS_LUT_USAGE_MAX]; struct sde_qos_lut_tbl qos_lut_tbl[SDE_QOS_LUT_USAGE_MAX]; u64 *danger_lut; u64 *safe_lut; u64 *creq_lut; u32 qos_refresh_count; u32 *qos_refresh_rate; struct sde_perf_cdp_cfg cdp_cfg[SDE_PERF_CDP_USAGE_MAX]; u32 cpu_mask; u32 cpu_dma_latency; Loading Loading @@ -1276,7 +1258,6 @@ struct sde_limit_cfg { * @has_qsync Supports qsync feature * @has_3d_merge_reset Supports 3D merge reset * @has_decimation Supports decimation * @has_qos_fl_nocalc flag to indicate QoS fill level needs no calculation * @update_tcsr_disp_glitch flag to enable HW workaround to avoid spurious * transactions during suspend * @has_base_layer Supports staging layer as base layer Loading Loading @@ -1335,7 +1316,6 @@ struct sde_mdss_cfg { bool has_qsync; bool has_3d_merge_reset; bool has_decimation; bool has_qos_fl_nocalc; bool update_tcsr_disp_glitch; bool has_base_layer; Loading
msm/sde/sde_hw_sspp.c +3 −13 Original line number Diff line number Diff line Loading @@ -844,7 +844,7 @@ static void sde_hw_sspp_setup_solidfill(struct sde_hw_pipe *ctx, u32 color, enum color); } static void sde_hw_sspp_setup_danger_safe_lut(struct sde_hw_pipe *ctx, static void sde_hw_sspp_setup_qos_lut(struct sde_hw_pipe *ctx, struct sde_hw_pipe_qos_cfg *cfg) { u32 idx; Loading @@ -854,15 +854,6 @@ static void sde_hw_sspp_setup_danger_safe_lut(struct sde_hw_pipe *ctx, SDE_REG_WRITE(&ctx->hw, SSPP_DANGER_LUT + idx, cfg->danger_lut); SDE_REG_WRITE(&ctx->hw, SSPP_SAFE_LUT + idx, cfg->safe_lut); } static void sde_hw_sspp_setup_creq_lut(struct sde_hw_pipe *ctx, struct sde_hw_pipe_qos_cfg *cfg) { u32 idx; if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx)) return; if (ctx->cap && test_bit(SDE_PERF_SSPP_QOS_8LVL, &ctx->cap->perf_features)) { Loading Loading @@ -1224,9 +1215,8 @@ static void _setup_layer_ops(struct sde_hw_pipe *c, c->ops.setup_excl_rect = _sde_hw_sspp_setup_excl_rect; if (test_bit(SDE_PERF_SSPP_QOS, &features)) { c->ops.setup_danger_safe_lut = sde_hw_sspp_setup_danger_safe_lut; c->ops.setup_creq_lut = sde_hw_sspp_setup_creq_lut; c->ops.setup_qos_lut = sde_hw_sspp_setup_qos_lut; c->ops.setup_qos_ctrl = sde_hw_sspp_setup_qos_ctrl; } Loading
msm/sde/sde_hw_sspp.h +2 −11 Original line number Diff line number Diff line Loading @@ -460,21 +460,12 @@ struct sde_hw_sspp_ops { enum sde_sspp_multirect_index idx); /** * setup_danger_safe_lut - setup danger safe LUTs * setup_qos_lut - setup danger, safe, creq LUTs * @ctx: Pointer to pipe context * @cfg: Pointer to pipe QoS configuration * */ void (*setup_danger_safe_lut)(struct sde_hw_pipe *ctx, struct sde_hw_pipe_qos_cfg *cfg); /** * setup_creq_lut - setup CREQ LUT * @ctx: Pointer to pipe context * @cfg: Pointer to pipe QoS configuration * */ void (*setup_creq_lut)(struct sde_hw_pipe *ctx, void (*setup_qos_lut)(struct sde_hw_pipe *ctx, struct sde_hw_pipe_qos_cfg *cfg); /** Loading