Loading Documentation/devicetree/bindings/display/msm/sde.txt +7 −0 Original line number Diff line number Diff line Loading @@ -297,6 +297,10 @@ Optional properties: - qcom,sde-downscaling-prefill-lines: A u32 value indicates the latency of downscaling in lines. - qcom,sde-max-per-pipe-bw-kbps: Array of u32 value indicates the max per pipe bandwidth in Kbps. - qcom,sde-amortizable-threshold: This value indicates the min for traffic shaping in lines. - qcom,sde-vbif-qos-rt-remap: This array is used to program vbif qos remapper register priority for realtime clients. - qcom,sde-vbif-qos-nrt-remap: This array is used to program vbif qos remapper register priority for non-realtime clients. Bus Scaling Subnodes: - qcom,sde-reg-bus: Property to provide Bus scaling for register access for Loading Loading @@ -500,6 +504,9 @@ Example: 2400000 2400000 2400000 2400000>; qcom,sde-amortizable-threshold = <11>; qcom,sde-vbif-qos-rt-remap = <3 3 4 4 5 5 6 6>; qcom,sde-vbif-qos-nrt-remap = <3 3 3 3 3 3 3 3>; qcom,sde-sspp-vig-blocks { qcom,sde-vig-csc-off = <0x320>; qcom,sde-vig-qseed-off = <0x200>; Loading drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c +45 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include "sde_core_irq.h" #include "sde_wb.h" #include "sde_vbif.h" #include "sde_crtc.h" #define to_sde_encoder_phys_wb(x) \ container_of(x, struct sde_encoder_phys_wb, base) Loading Loading @@ -103,6 +104,48 @@ static void sde_encoder_phys_wb_set_traffic_shaper( wb_cfg->ts_cfg.en = false; } /** * sde_encoder_phys_wb_set_qos_remap - set QoS remapper for writeback * @phys_enc: Pointer to physical encoder */ static void sde_encoder_phys_wb_set_qos_remap( struct sde_encoder_phys *phys_enc) { struct sde_encoder_phys_wb *wb_enc; struct sde_hw_wb *hw_wb; struct drm_crtc *crtc; struct sde_vbif_set_qos_params qos_params; if (!phys_enc || !phys_enc->parent || !phys_enc->parent->crtc) { SDE_ERROR("invalid arguments\n"); return; } wb_enc = to_sde_encoder_phys_wb(phys_enc); crtc = phys_enc->parent->crtc; if (!wb_enc->hw_wb || !wb_enc->hw_wb->caps) { SDE_ERROR("invalid writeback hardware\n"); return; } hw_wb = wb_enc->hw_wb; memset(&qos_params, 0, sizeof(qos_params)); qos_params.vbif_idx = hw_wb->caps->vbif_idx; qos_params.xin_id = hw_wb->caps->xin_id; qos_params.clk_ctrl = hw_wb->caps->clk_ctrl; qos_params.num = hw_wb->idx - WB_0; qos_params.is_rt = sde_crtc_get_client_type(crtc) != NRT_CLIENT; SDE_DEBUG("[qos_remap] wb:%d vbif:%d xin:%d rt:%d\n", qos_params.num, qos_params.vbif_idx, qos_params.xin_id, qos_params.is_rt); sde_vbif_set_qos_remap(phys_enc->sde_kms, &qos_params); } /** * sde_encoder_phys_setup_cdm - setup chroma down block * @phys_enc: Pointer to physical encoder Loading Loading @@ -528,6 +571,8 @@ static void sde_encoder_phys_wb_setup( sde_encoder_phys_wb_set_traffic_shaper(phys_enc); sde_encoder_phys_wb_set_qos_remap(phys_enc); sde_encoder_phys_setup_cdm(phys_enc, fb, wb_enc->wb_fmt, wb_roi); sde_encoder_phys_wb_setup_fb(phys_enc, fb, wb_roi); Loading drivers/gpu/drm/msm/sde/sde_hw_catalog.c +81 −4 Original line number Diff line number Diff line Loading @@ -285,6 +285,8 @@ enum { VBIF_DEFAULT_OT_WR_LIMIT, VBIF_DYNAMIC_OT_RD_LIMIT, VBIF_DYNAMIC_OT_WR_LIMIT, VBIF_QOS_RT_REMAP, VBIF_QOS_NRT_REMAP, VBIF_PROP_MAX, }; Loading Loading @@ -512,6 +514,10 @@ static struct sde_prop_type vbif_prop[] = { PROP_TYPE_U32_ARRAY}, {VBIF_DYNAMIC_OT_WR_LIMIT, "qcom,sde-vbif-dynamic-ot-wr-limit", false, PROP_TYPE_U32_ARRAY}, {VBIF_QOS_RT_REMAP, "qcom,sde-vbif-qos-rt-remap", false, PROP_TYPE_U32_ARRAY}, {VBIF_QOS_NRT_REMAP, "qcom,sde-vbif-qos-nrt-remap", false, PROP_TYPE_U32_ARRAY}, }; static struct sde_prop_type reg_dma_prop[REG_DMA_PROP_MAX] = { Loading Loading @@ -1926,7 +1932,7 @@ static int sde_vbif_parse_dt(struct device_node *np, int rc, prop_count[VBIF_PROP_MAX], i, j, k; struct sde_prop_value *prop_value = NULL; bool prop_exists[VBIF_PROP_MAX]; u32 off_count, vbif_len, rd_len = 0, wr_len = 0; u32 off_count, vbif_len; struct sde_vbif_cfg *vbif; if (!sde_cfg) { Loading @@ -1948,12 +1954,22 @@ static int sde_vbif_parse_dt(struct device_node *np, goto end; rc = _validate_dt_entry(np, &vbif_prop[VBIF_DYNAMIC_OT_RD_LIMIT], 1, &prop_count[VBIF_DYNAMIC_OT_RD_LIMIT], &rd_len); &prop_count[VBIF_DYNAMIC_OT_RD_LIMIT], NULL); if (rc) goto end; rc = _validate_dt_entry(np, &vbif_prop[VBIF_DYNAMIC_OT_WR_LIMIT], 1, &prop_count[VBIF_DYNAMIC_OT_WR_LIMIT], &wr_len); &prop_count[VBIF_DYNAMIC_OT_WR_LIMIT], NULL); if (rc) goto end; rc = _validate_dt_entry(np, &vbif_prop[VBIF_QOS_RT_REMAP], 1, &prop_count[VBIF_QOS_RT_REMAP], NULL); if (rc) goto end; rc = _validate_dt_entry(np, &vbif_prop[VBIF_QOS_NRT_REMAP], 1, &prop_count[VBIF_QOS_NRT_REMAP], NULL); if (rc) goto end; Loading Loading @@ -2048,6 +2064,63 @@ static int sde_vbif_parse_dt(struct device_node *np, vbif->dynamic_ot_rd_tbl.count || vbif->dynamic_ot_wr_tbl.count) set_bit(SDE_VBIF_QOS_OTLIM, &vbif->features); vbif->qos_rt_tbl.npriority_lvl = prop_count[VBIF_QOS_RT_REMAP]; SDE_DEBUG("qos_rt_tbl.npriority_lvl=%u\n", vbif->qos_rt_tbl.npriority_lvl); if (vbif->qos_rt_tbl.npriority_lvl == sde_cfg->vbif_qos_nlvl) { vbif->qos_rt_tbl.priority_lvl = kcalloc( vbif->qos_rt_tbl.npriority_lvl, sizeof(u32), GFP_KERNEL); if (!vbif->qos_rt_tbl.priority_lvl) { rc = -ENOMEM; goto end; } } else if (vbif->qos_rt_tbl.npriority_lvl) { vbif->qos_rt_tbl.npriority_lvl = 0; vbif->qos_rt_tbl.priority_lvl = NULL; SDE_ERROR("invalid qos rt table\n"); } for (j = 0; j < vbif->qos_rt_tbl.npriority_lvl; j++) { vbif->qos_rt_tbl.priority_lvl[j] = PROP_VALUE_ACCESS(prop_value, VBIF_QOS_RT_REMAP, j); SDE_DEBUG("lvl[%d]=%u\n", j, vbif->qos_rt_tbl.priority_lvl[j]); } vbif->qos_nrt_tbl.npriority_lvl = prop_count[VBIF_QOS_NRT_REMAP]; SDE_DEBUG("qos_nrt_tbl.npriority_lvl=%u\n", vbif->qos_nrt_tbl.npriority_lvl); if (vbif->qos_nrt_tbl.npriority_lvl == sde_cfg->vbif_qos_nlvl) { vbif->qos_nrt_tbl.priority_lvl = kcalloc( vbif->qos_nrt_tbl.npriority_lvl, sizeof(u32), GFP_KERNEL); if (!vbif->qos_nrt_tbl.priority_lvl) { rc = -ENOMEM; goto end; } } else if (vbif->qos_nrt_tbl.npriority_lvl) { vbif->qos_nrt_tbl.npriority_lvl = 0; vbif->qos_nrt_tbl.priority_lvl = NULL; SDE_ERROR("invalid qos nrt table\n"); } for (j = 0; j < vbif->qos_nrt_tbl.npriority_lvl; j++) { vbif->qos_nrt_tbl.priority_lvl[j] = PROP_VALUE_ACCESS(prop_value, VBIF_QOS_NRT_REMAP, j); SDE_DEBUG("lvl[%d]=%u\n", j, vbif->qos_nrt_tbl.priority_lvl[j]); } if (vbif->qos_rt_tbl.npriority_lvl || vbif->qos_nrt_tbl.npriority_lvl) set_bit(SDE_VBIF_QOS_REMAP, &vbif->features); } end: Loading Loading @@ -2510,11 +2583,13 @@ static int _sde_hardware_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) /* update msm8998 target here */ sde_cfg->has_wb_ubwc = true; sde_cfg->perf.min_prefill_lines = 25; sde_cfg->vbif_qos_nlvl = 4; break; case SDE_HW_VER_400: /* update msm8998 and sdm845 target here */ /* update sdm845 target here */ sde_cfg->has_wb_ubwc = true; sde_cfg->perf.min_prefill_lines = 24; sde_cfg->vbif_qos_nlvl = 8; break; default: sde_cfg->perf.min_prefill_lines = 0xffff; Loading Loading @@ -2549,6 +2624,8 @@ void sde_hw_catalog_deinit(struct sde_mdss_cfg *sde_cfg) for (i = 0; i < sde_cfg->vbif_count; i++) { kfree(sde_cfg->vbif[i].dynamic_ot_rd_tbl.cfg); kfree(sde_cfg->vbif[i].dynamic_ot_wr_tbl.cfg); kfree(sde_cfg->vbif[i].qos_rt_tbl.priority_lvl); kfree(sde_cfg->vbif[i].qos_nrt_tbl.priority_lvl); } kfree(sde_cfg->dma_formats); Loading drivers/gpu/drm/msm/sde/sde_hw_catalog.h +18 −0 Original line number Diff line number Diff line Loading @@ -258,10 +258,12 @@ enum { /** * VBIF sub-blocks and features * @SDE_VBIF_QOS_OTLIM VBIF supports OT Limit * @SDE_VBIF_QOS_REMAP VBIF supports QoS priority remap * @SDE_VBIF_MAX maximum value */ enum { SDE_VBIF_QOS_OTLIM = 0x1, SDE_VBIF_QOS_REMAP, SDE_VBIF_MAX }; Loading Loading @@ -652,6 +654,16 @@ struct sde_vbif_dynamic_ot_tbl { struct sde_vbif_dynamic_ot_cfg *cfg; }; /** * struct sde_vbif_qos_tbl - QoS priority table * @npriority_lvl num of priority level * @priority_lvl pointer to array of priority level in ascending order */ struct sde_vbif_qos_tbl { u32 npriority_lvl; u32 *priority_lvl; }; /** * struct sde_vbif_cfg - information of VBIF blocks * @id enum identifying this block Loading @@ -662,6 +674,8 @@ struct sde_vbif_dynamic_ot_tbl { * @xin_halt_timeout maximum time (in usec) for xin to halt * @dynamic_ot_rd_tbl dynamic OT read configuration table * @dynamic_ot_wr_tbl dynamic OT write configuration table * @qos_rt_tbl real-time QoS priority table * @qos_nrt_tbl non-real-time QoS priority table */ struct sde_vbif_cfg { SDE_HW_BLK_INFO; Loading @@ -670,6 +684,8 @@ struct sde_vbif_cfg { u32 xin_halt_timeout; struct sde_vbif_dynamic_ot_tbl dynamic_ot_rd_tbl; struct sde_vbif_dynamic_ot_tbl dynamic_ot_wr_tbl; struct sde_vbif_qos_tbl qos_rt_tbl; struct sde_vbif_qos_tbl qos_nrt_tbl; }; /** * struct sde_reg_dma_cfg - information of lut dma blocks Loading Loading @@ -746,6 +762,7 @@ struct sde_perf_cfg { * @cursor_formats Supported formats for cursor pipe * @vig_formats Supported formats for vig pipe * @wb_formats Supported formats for wb * @vbif_qos_nlvl number of vbif QoS priority level */ struct sde_mdss_cfg { u32 hwversion; Loading @@ -765,6 +782,7 @@ struct sde_mdss_cfg { bool has_sbuf; u32 sbuf_headroom; bool has_idle_pc; u32 vbif_qos_nlvl; u32 mdss_count; struct sde_mdss_base_cfg mdss[MAX_BLOCKS]; Loading drivers/gpu/drm/msm/sde/sde_hw_vbif.c +33 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,8 @@ #define VBIF_OUT_WR_LIM_CONF0 0x00D4 #define VBIF_XIN_HALT_CTRL0 0x0200 #define VBIF_XIN_HALT_CTRL1 0x0204 #define VBIF_XINL_QOS_RP_REMAP_000 0x0550 #define VBIF_XINL_QOS_LVL_REMAP_000 0x0590 static void sde_hw_set_limit_conf(struct sde_hw_vbif *vbif, u32 xin_id, bool rd, u32 limit) Loading Loading @@ -104,6 +106,35 @@ static bool sde_hw_get_halt_ctrl(struct sde_hw_vbif *vbif, return (reg_val & BIT(xin_id)) ? true : false; } static void sde_hw_set_qos_remap(struct sde_hw_vbif *vbif, u32 xin_id, u32 level, u32 remap_level) { struct sde_hw_blk_reg_map *c; u32 reg_val, reg_val_lvl, mask, reg_high, reg_shift; if (!vbif) return; c = &vbif->hw; reg_high = ((xin_id & 0x8) >> 3) * 4 + (level * 8); reg_shift = (xin_id & 0x7) * 4; reg_val = SDE_REG_READ(c, VBIF_XINL_QOS_RP_REMAP_000 + reg_high); reg_val_lvl = SDE_REG_READ(c, VBIF_XINL_QOS_LVL_REMAP_000 + reg_high); mask = 0x7 << reg_shift; reg_val &= ~mask; reg_val |= (remap_level << reg_shift) & mask; reg_val_lvl &= ~mask; reg_val_lvl |= (remap_level << reg_shift) & mask; SDE_REG_WRITE(c, VBIF_XINL_QOS_RP_REMAP_000 + reg_high, reg_val); SDE_REG_WRITE(c, VBIF_XINL_QOS_LVL_REMAP_000 + reg_high, reg_val_lvl); } static void _setup_vbif_ops(struct sde_hw_vbif_ops *ops, unsigned long cap) { Loading @@ -111,6 +142,8 @@ static void _setup_vbif_ops(struct sde_hw_vbif_ops *ops, ops->get_limit_conf = sde_hw_get_limit_conf; ops->set_halt_ctrl = sde_hw_set_halt_ctrl; ops->get_halt_ctrl = sde_hw_get_halt_ctrl; if (test_bit(SDE_VBIF_QOS_REMAP, &cap)) ops->set_qos_remap = sde_hw_set_qos_remap; } static const struct sde_vbif_cfg *_top_offset(enum sde_vbif vbif, Loading Loading
Documentation/devicetree/bindings/display/msm/sde.txt +7 −0 Original line number Diff line number Diff line Loading @@ -297,6 +297,10 @@ Optional properties: - qcom,sde-downscaling-prefill-lines: A u32 value indicates the latency of downscaling in lines. - qcom,sde-max-per-pipe-bw-kbps: Array of u32 value indicates the max per pipe bandwidth in Kbps. - qcom,sde-amortizable-threshold: This value indicates the min for traffic shaping in lines. - qcom,sde-vbif-qos-rt-remap: This array is used to program vbif qos remapper register priority for realtime clients. - qcom,sde-vbif-qos-nrt-remap: This array is used to program vbif qos remapper register priority for non-realtime clients. Bus Scaling Subnodes: - qcom,sde-reg-bus: Property to provide Bus scaling for register access for Loading Loading @@ -500,6 +504,9 @@ Example: 2400000 2400000 2400000 2400000>; qcom,sde-amortizable-threshold = <11>; qcom,sde-vbif-qos-rt-remap = <3 3 4 4 5 5 6 6>; qcom,sde-vbif-qos-nrt-remap = <3 3 3 3 3 3 3 3>; qcom,sde-sspp-vig-blocks { qcom,sde-vig-csc-off = <0x320>; qcom,sde-vig-qseed-off = <0x200>; Loading
drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c +45 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include "sde_core_irq.h" #include "sde_wb.h" #include "sde_vbif.h" #include "sde_crtc.h" #define to_sde_encoder_phys_wb(x) \ container_of(x, struct sde_encoder_phys_wb, base) Loading Loading @@ -103,6 +104,48 @@ static void sde_encoder_phys_wb_set_traffic_shaper( wb_cfg->ts_cfg.en = false; } /** * sde_encoder_phys_wb_set_qos_remap - set QoS remapper for writeback * @phys_enc: Pointer to physical encoder */ static void sde_encoder_phys_wb_set_qos_remap( struct sde_encoder_phys *phys_enc) { struct sde_encoder_phys_wb *wb_enc; struct sde_hw_wb *hw_wb; struct drm_crtc *crtc; struct sde_vbif_set_qos_params qos_params; if (!phys_enc || !phys_enc->parent || !phys_enc->parent->crtc) { SDE_ERROR("invalid arguments\n"); return; } wb_enc = to_sde_encoder_phys_wb(phys_enc); crtc = phys_enc->parent->crtc; if (!wb_enc->hw_wb || !wb_enc->hw_wb->caps) { SDE_ERROR("invalid writeback hardware\n"); return; } hw_wb = wb_enc->hw_wb; memset(&qos_params, 0, sizeof(qos_params)); qos_params.vbif_idx = hw_wb->caps->vbif_idx; qos_params.xin_id = hw_wb->caps->xin_id; qos_params.clk_ctrl = hw_wb->caps->clk_ctrl; qos_params.num = hw_wb->idx - WB_0; qos_params.is_rt = sde_crtc_get_client_type(crtc) != NRT_CLIENT; SDE_DEBUG("[qos_remap] wb:%d vbif:%d xin:%d rt:%d\n", qos_params.num, qos_params.vbif_idx, qos_params.xin_id, qos_params.is_rt); sde_vbif_set_qos_remap(phys_enc->sde_kms, &qos_params); } /** * sde_encoder_phys_setup_cdm - setup chroma down block * @phys_enc: Pointer to physical encoder Loading Loading @@ -528,6 +571,8 @@ static void sde_encoder_phys_wb_setup( sde_encoder_phys_wb_set_traffic_shaper(phys_enc); sde_encoder_phys_wb_set_qos_remap(phys_enc); sde_encoder_phys_setup_cdm(phys_enc, fb, wb_enc->wb_fmt, wb_roi); sde_encoder_phys_wb_setup_fb(phys_enc, fb, wb_roi); Loading
drivers/gpu/drm/msm/sde/sde_hw_catalog.c +81 −4 Original line number Diff line number Diff line Loading @@ -285,6 +285,8 @@ enum { VBIF_DEFAULT_OT_WR_LIMIT, VBIF_DYNAMIC_OT_RD_LIMIT, VBIF_DYNAMIC_OT_WR_LIMIT, VBIF_QOS_RT_REMAP, VBIF_QOS_NRT_REMAP, VBIF_PROP_MAX, }; Loading Loading @@ -512,6 +514,10 @@ static struct sde_prop_type vbif_prop[] = { PROP_TYPE_U32_ARRAY}, {VBIF_DYNAMIC_OT_WR_LIMIT, "qcom,sde-vbif-dynamic-ot-wr-limit", false, PROP_TYPE_U32_ARRAY}, {VBIF_QOS_RT_REMAP, "qcom,sde-vbif-qos-rt-remap", false, PROP_TYPE_U32_ARRAY}, {VBIF_QOS_NRT_REMAP, "qcom,sde-vbif-qos-nrt-remap", false, PROP_TYPE_U32_ARRAY}, }; static struct sde_prop_type reg_dma_prop[REG_DMA_PROP_MAX] = { Loading Loading @@ -1926,7 +1932,7 @@ static int sde_vbif_parse_dt(struct device_node *np, int rc, prop_count[VBIF_PROP_MAX], i, j, k; struct sde_prop_value *prop_value = NULL; bool prop_exists[VBIF_PROP_MAX]; u32 off_count, vbif_len, rd_len = 0, wr_len = 0; u32 off_count, vbif_len; struct sde_vbif_cfg *vbif; if (!sde_cfg) { Loading @@ -1948,12 +1954,22 @@ static int sde_vbif_parse_dt(struct device_node *np, goto end; rc = _validate_dt_entry(np, &vbif_prop[VBIF_DYNAMIC_OT_RD_LIMIT], 1, &prop_count[VBIF_DYNAMIC_OT_RD_LIMIT], &rd_len); &prop_count[VBIF_DYNAMIC_OT_RD_LIMIT], NULL); if (rc) goto end; rc = _validate_dt_entry(np, &vbif_prop[VBIF_DYNAMIC_OT_WR_LIMIT], 1, &prop_count[VBIF_DYNAMIC_OT_WR_LIMIT], &wr_len); &prop_count[VBIF_DYNAMIC_OT_WR_LIMIT], NULL); if (rc) goto end; rc = _validate_dt_entry(np, &vbif_prop[VBIF_QOS_RT_REMAP], 1, &prop_count[VBIF_QOS_RT_REMAP], NULL); if (rc) goto end; rc = _validate_dt_entry(np, &vbif_prop[VBIF_QOS_NRT_REMAP], 1, &prop_count[VBIF_QOS_NRT_REMAP], NULL); if (rc) goto end; Loading Loading @@ -2048,6 +2064,63 @@ static int sde_vbif_parse_dt(struct device_node *np, vbif->dynamic_ot_rd_tbl.count || vbif->dynamic_ot_wr_tbl.count) set_bit(SDE_VBIF_QOS_OTLIM, &vbif->features); vbif->qos_rt_tbl.npriority_lvl = prop_count[VBIF_QOS_RT_REMAP]; SDE_DEBUG("qos_rt_tbl.npriority_lvl=%u\n", vbif->qos_rt_tbl.npriority_lvl); if (vbif->qos_rt_tbl.npriority_lvl == sde_cfg->vbif_qos_nlvl) { vbif->qos_rt_tbl.priority_lvl = kcalloc( vbif->qos_rt_tbl.npriority_lvl, sizeof(u32), GFP_KERNEL); if (!vbif->qos_rt_tbl.priority_lvl) { rc = -ENOMEM; goto end; } } else if (vbif->qos_rt_tbl.npriority_lvl) { vbif->qos_rt_tbl.npriority_lvl = 0; vbif->qos_rt_tbl.priority_lvl = NULL; SDE_ERROR("invalid qos rt table\n"); } for (j = 0; j < vbif->qos_rt_tbl.npriority_lvl; j++) { vbif->qos_rt_tbl.priority_lvl[j] = PROP_VALUE_ACCESS(prop_value, VBIF_QOS_RT_REMAP, j); SDE_DEBUG("lvl[%d]=%u\n", j, vbif->qos_rt_tbl.priority_lvl[j]); } vbif->qos_nrt_tbl.npriority_lvl = prop_count[VBIF_QOS_NRT_REMAP]; SDE_DEBUG("qos_nrt_tbl.npriority_lvl=%u\n", vbif->qos_nrt_tbl.npriority_lvl); if (vbif->qos_nrt_tbl.npriority_lvl == sde_cfg->vbif_qos_nlvl) { vbif->qos_nrt_tbl.priority_lvl = kcalloc( vbif->qos_nrt_tbl.npriority_lvl, sizeof(u32), GFP_KERNEL); if (!vbif->qos_nrt_tbl.priority_lvl) { rc = -ENOMEM; goto end; } } else if (vbif->qos_nrt_tbl.npriority_lvl) { vbif->qos_nrt_tbl.npriority_lvl = 0; vbif->qos_nrt_tbl.priority_lvl = NULL; SDE_ERROR("invalid qos nrt table\n"); } for (j = 0; j < vbif->qos_nrt_tbl.npriority_lvl; j++) { vbif->qos_nrt_tbl.priority_lvl[j] = PROP_VALUE_ACCESS(prop_value, VBIF_QOS_NRT_REMAP, j); SDE_DEBUG("lvl[%d]=%u\n", j, vbif->qos_nrt_tbl.priority_lvl[j]); } if (vbif->qos_rt_tbl.npriority_lvl || vbif->qos_nrt_tbl.npriority_lvl) set_bit(SDE_VBIF_QOS_REMAP, &vbif->features); } end: Loading Loading @@ -2510,11 +2583,13 @@ static int _sde_hardware_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) /* update msm8998 target here */ sde_cfg->has_wb_ubwc = true; sde_cfg->perf.min_prefill_lines = 25; sde_cfg->vbif_qos_nlvl = 4; break; case SDE_HW_VER_400: /* update msm8998 and sdm845 target here */ /* update sdm845 target here */ sde_cfg->has_wb_ubwc = true; sde_cfg->perf.min_prefill_lines = 24; sde_cfg->vbif_qos_nlvl = 8; break; default: sde_cfg->perf.min_prefill_lines = 0xffff; Loading Loading @@ -2549,6 +2624,8 @@ void sde_hw_catalog_deinit(struct sde_mdss_cfg *sde_cfg) for (i = 0; i < sde_cfg->vbif_count; i++) { kfree(sde_cfg->vbif[i].dynamic_ot_rd_tbl.cfg); kfree(sde_cfg->vbif[i].dynamic_ot_wr_tbl.cfg); kfree(sde_cfg->vbif[i].qos_rt_tbl.priority_lvl); kfree(sde_cfg->vbif[i].qos_nrt_tbl.priority_lvl); } kfree(sde_cfg->dma_formats); Loading
drivers/gpu/drm/msm/sde/sde_hw_catalog.h +18 −0 Original line number Diff line number Diff line Loading @@ -258,10 +258,12 @@ enum { /** * VBIF sub-blocks and features * @SDE_VBIF_QOS_OTLIM VBIF supports OT Limit * @SDE_VBIF_QOS_REMAP VBIF supports QoS priority remap * @SDE_VBIF_MAX maximum value */ enum { SDE_VBIF_QOS_OTLIM = 0x1, SDE_VBIF_QOS_REMAP, SDE_VBIF_MAX }; Loading Loading @@ -652,6 +654,16 @@ struct sde_vbif_dynamic_ot_tbl { struct sde_vbif_dynamic_ot_cfg *cfg; }; /** * struct sde_vbif_qos_tbl - QoS priority table * @npriority_lvl num of priority level * @priority_lvl pointer to array of priority level in ascending order */ struct sde_vbif_qos_tbl { u32 npriority_lvl; u32 *priority_lvl; }; /** * struct sde_vbif_cfg - information of VBIF blocks * @id enum identifying this block Loading @@ -662,6 +674,8 @@ struct sde_vbif_dynamic_ot_tbl { * @xin_halt_timeout maximum time (in usec) for xin to halt * @dynamic_ot_rd_tbl dynamic OT read configuration table * @dynamic_ot_wr_tbl dynamic OT write configuration table * @qos_rt_tbl real-time QoS priority table * @qos_nrt_tbl non-real-time QoS priority table */ struct sde_vbif_cfg { SDE_HW_BLK_INFO; Loading @@ -670,6 +684,8 @@ struct sde_vbif_cfg { u32 xin_halt_timeout; struct sde_vbif_dynamic_ot_tbl dynamic_ot_rd_tbl; struct sde_vbif_dynamic_ot_tbl dynamic_ot_wr_tbl; struct sde_vbif_qos_tbl qos_rt_tbl; struct sde_vbif_qos_tbl qos_nrt_tbl; }; /** * struct sde_reg_dma_cfg - information of lut dma blocks Loading Loading @@ -746,6 +762,7 @@ struct sde_perf_cfg { * @cursor_formats Supported formats for cursor pipe * @vig_formats Supported formats for vig pipe * @wb_formats Supported formats for wb * @vbif_qos_nlvl number of vbif QoS priority level */ struct sde_mdss_cfg { u32 hwversion; Loading @@ -765,6 +782,7 @@ struct sde_mdss_cfg { bool has_sbuf; u32 sbuf_headroom; bool has_idle_pc; u32 vbif_qos_nlvl; u32 mdss_count; struct sde_mdss_base_cfg mdss[MAX_BLOCKS]; Loading
drivers/gpu/drm/msm/sde/sde_hw_vbif.c +33 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,8 @@ #define VBIF_OUT_WR_LIM_CONF0 0x00D4 #define VBIF_XIN_HALT_CTRL0 0x0200 #define VBIF_XIN_HALT_CTRL1 0x0204 #define VBIF_XINL_QOS_RP_REMAP_000 0x0550 #define VBIF_XINL_QOS_LVL_REMAP_000 0x0590 static void sde_hw_set_limit_conf(struct sde_hw_vbif *vbif, u32 xin_id, bool rd, u32 limit) Loading Loading @@ -104,6 +106,35 @@ static bool sde_hw_get_halt_ctrl(struct sde_hw_vbif *vbif, return (reg_val & BIT(xin_id)) ? true : false; } static void sde_hw_set_qos_remap(struct sde_hw_vbif *vbif, u32 xin_id, u32 level, u32 remap_level) { struct sde_hw_blk_reg_map *c; u32 reg_val, reg_val_lvl, mask, reg_high, reg_shift; if (!vbif) return; c = &vbif->hw; reg_high = ((xin_id & 0x8) >> 3) * 4 + (level * 8); reg_shift = (xin_id & 0x7) * 4; reg_val = SDE_REG_READ(c, VBIF_XINL_QOS_RP_REMAP_000 + reg_high); reg_val_lvl = SDE_REG_READ(c, VBIF_XINL_QOS_LVL_REMAP_000 + reg_high); mask = 0x7 << reg_shift; reg_val &= ~mask; reg_val |= (remap_level << reg_shift) & mask; reg_val_lvl &= ~mask; reg_val_lvl |= (remap_level << reg_shift) & mask; SDE_REG_WRITE(c, VBIF_XINL_QOS_RP_REMAP_000 + reg_high, reg_val); SDE_REG_WRITE(c, VBIF_XINL_QOS_LVL_REMAP_000 + reg_high, reg_val_lvl); } static void _setup_vbif_ops(struct sde_hw_vbif_ops *ops, unsigned long cap) { Loading @@ -111,6 +142,8 @@ static void _setup_vbif_ops(struct sde_hw_vbif_ops *ops, ops->get_limit_conf = sde_hw_get_limit_conf; ops->set_halt_ctrl = sde_hw_set_halt_ctrl; ops->get_halt_ctrl = sde_hw_get_halt_ctrl; if (test_bit(SDE_VBIF_QOS_REMAP, &cap)) ops->set_qos_remap = sde_hw_set_qos_remap; } static const struct sde_vbif_cfg *_top_offset(enum sde_vbif vbif, Loading