From c3991049c199efe8544f5df363327079cdcfd04c Mon Sep 17 00:00:00 2001 From: Prabhanjan Kandula Date: Thu, 23 Jun 2022 00:31:38 -0700 Subject: [PATCH] disp: msm: sde: add support for new QoS mode of WB rotation This change adds support for new dynamic QoS mode for WB rotation which is required to achieve rotation output available at required rate to meet real time use case. Though traffic shaper can be disabled in dynamic QoS mode, part of traffic shaper algo to track WB operating speed is enabled and WB generates creq priority based on current ouput rate compared to targetted ouput to help meeting real time use case requirement. Change-Id: I98c2dcae53f1b175dc49b40238b9da33e95717a6 Signed-off-by: Prabhanjan Kandula --- msm/msm_drv.h | 1 + msm/sde/sde_encoder_phys_wb.c | 23 ++++++++++++++++++----- msm/sde/sde_hw_wb.c | 6 ++++++ msm/sde/sde_hw_wb.h | 14 ++++++++++++++ msm/sde/sde_wb.c | 6 +++++- 5 files changed, 44 insertions(+), 6 deletions(-) diff --git a/msm/msm_drv.h b/msm/msm_drv.h index 761020687b..cd46594e2e 100644 --- a/msm/msm_drv.h +++ b/msm/msm_drv.h @@ -244,6 +244,7 @@ enum msm_mdp_conn_property { CONNECTOR_PROP_DSC_MODE, CONNECTOR_PROP_WB_USAGE_TYPE, CONNECTOR_PROP_WB_ROT_TYPE, + CONNECTOR_PROP_WB_ROT_BYTES_PER_CLK, /* total # of properties */ CONNECTOR_PROP_COUNT diff --git a/msm/sde/sde_encoder_phys_wb.c b/msm/sde/sde_encoder_phys_wb.c index 6ebb5087a4..7f5ab28002 100644 --- a/msm/sde/sde_encoder_phys_wb.c +++ b/msm/sde/sde_encoder_phys_wb.c @@ -101,8 +101,7 @@ static void sde_encoder_phys_wb_set_ot_limit(struct sde_encoder_phys *phys_enc) ot_params.num = hw_wb->idx - WB_0; ot_params.width = wb_enc->wb_roi.w; ot_params.height = wb_enc->wb_roi.h; - ot_params.is_wfd = ((phys_enc->in_clone_mode) || (usage_type == WB_USAGE_OFFLINE_WB)) ? - false : true; + ot_params.is_wfd = (usage_type == WB_USAGE_WFD); ot_params.frame_rate = drm_mode_vrefresh(&phys_enc->cached_mode); ot_params.vbif_idx = hw_wb->caps->vbif_idx; ot_params.clk_ctrl = hw_wb->caps->clk_ctrl; @@ -153,7 +152,7 @@ static void sde_encoder_phys_wb_set_qos_remap(struct sde_encoder_phys *phys_enc) qos_params.num = hw_wb->idx - WB_0; if (phys_enc->in_clone_mode) qos_params.client_type = VBIF_CWB_CLIENT; - else if (usage_type == WB_USAGE_OFFLINE_WB) + else if (usage_type == WB_USAGE_OFFLINE_WB || usage_type == WB_USAGE_ROT) qos_params.client_type = VBIF_OFFLINE_WB_CLIENT; else qos_params.client_type = VBIF_NRT_CLIENT; @@ -206,13 +205,19 @@ static void sde_encoder_phys_wb_set_qos(struct sde_encoder_phys *phys_enc) } qos_cfg.danger_safe_en = true; + if (usage_type == WB_USAGE_ROT) { + qos_cfg.danger_safe_en = false; + qos_cfg.qos_mode = SDE_WB_QOS_MODE_DYNAMIC; + qos_cfg.bytes_per_clk = sde_connector_get_property(conn_state, + CONNECTOR_PROP_WB_ROT_BYTES_PER_CLK); + } if (phys_enc->in_clone_mode) lut_index = (SDE_FORMAT_IS_TILE(wb_enc->wb_fmt) || SDE_FORMAT_IS_UBWC(wb_enc->wb_fmt)) ? SDE_QOS_LUT_USAGE_CWB_TILE : SDE_QOS_LUT_USAGE_CWB; else - lut_index = (usage_type == WB_USAGE_OFFLINE_WB) ? + lut_index = (usage_type == WB_USAGE_OFFLINE_WB || usage_type == WB_USAGE_ROT) ? SDE_QOS_LUT_USAGE_OFFLINE_WB : SDE_QOS_LUT_USAGE_NRT; creq_index = lut_index * SDE_CREQ_LUT_TYPE_MAX; @@ -996,14 +1001,15 @@ static int _sde_encoder_phys_wb_validate_rotation(struct sde_encoder_phys *phys_ enum sde_wb_rot_type rotation_type; int ret = 0; u32 src_w, src_h; + u32 bytes_per_clk; struct sde_rect wb_src, wb_roi = {0,}; struct sde_io_res dnsc_res = {0,}; const struct sde_rect *crtc_roi = NULL; struct drm_display_mode *mode; + enum sde_wb_usage_type usage_type; struct sde_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys_enc); rotation_type = sde_connector_get_property(conn_state, CONNECTOR_PROP_WB_ROT_TYPE); - if (rotation_type == WB_ROT_NONE) return ret; @@ -1014,6 +1020,13 @@ static int _sde_encoder_phys_wb_validate_rotation(struct sde_encoder_phys *phys_ return -EINVAL; } + bytes_per_clk = sde_connector_get_property(conn_state, CONNECTOR_PROP_WB_ROT_BYTES_PER_CLK); + if (!bytes_per_clk) { + SDE_ERROR("[enc:%d wb:%d] WB output bytes per XO clock is must for rotation\n", + DRMID(phys_enc->parent), WBID(wb_enc)); + return -EINVAL; + } + ret = sde_wb_connector_state_get_output_roi(conn_state, &wb_roi); if (ret) { SDE_ERROR("[enc:%d wb:%d] failed to get WB output roi, ret:%d\n", diff --git a/msm/sde/sde_hw_wb.c b/msm/sde/sde_hw_wb.c index 68199ca6ea..4c010451ee 100644 --- a/msm/sde/sde_hw_wb.c +++ b/msm/sde/sde_hw_wb.c @@ -23,6 +23,7 @@ #define WB_DST3_ADDR 0x018 #define WB_DST_YSTRIDE0 0x01C #define WB_DST_YSTRIDE1 0x020 +#define WB_TS_WR_CLIENT 0x040 #define WB_DST_WRITE_CONFIG 0x048 #define WB_OUT_SIZE 0x074 #define WB_ALPHA_X_VALUE 0x078 @@ -307,6 +308,11 @@ static void sde_hw_wb_setup_qos_lut(struct sde_hw_wb *ctx, if (cfg->danger_safe_en) qos_ctrl |= WB_QOS_CTRL_DANGER_SAFE_EN; + if (test_bit(SDE_WB_LINEAR_ROTATION, &ctx->caps->features)) { + SDE_REG_WRITE(c, WB_TS_WR_CLIENT, cfg->bytes_per_clk & 0xFF); + qos_ctrl |= (cfg->qos_mode << 1); + } + SDE_REG_WRITE(c, WB_QOS_CTRL, qos_ctrl); } diff --git a/msm/sde/sde_hw_wb.h b/msm/sde/sde_hw_wb.h index a2a6bbea4d..87c5400038 100644 --- a/msm/sde/sde_hw_wb.h +++ b/msm/sde/sde_hw_wb.h @@ -49,17 +49,31 @@ struct sde_hw_wb_cdp_cfg { u32 preload_ahead; }; +/** + * enum sde_hw_wb_qos_mode: enumeration of available QOS modes for WB + * @SDE_WB_QOS_MODE_STATIC: static qos mode same as existing NRT qos mode + * @SDE_WB_QOS_MODE_DYNAMIC: new qos mode to support rotation for real time + */ +enum sde_hw_wb_qos_mode { + SDE_WB_QOS_MODE_STATIC, + SDE_WB_QOS_MODE_DYNAMIC, +}; + /** * struct sde_hw_wb_qos_cfg : Writeback pipe QoS configuration * @danger_lut: LUT for generate danger level based on fill level * @safe_lut: LUT for generate safe level based on fill level * @creq_lut: LUT for generate creq level based on fill level + * @bytes_per_clk: WB output bytes per XO clock value used in rotation + * @qos_mode: enum value mapped for selecting WB QOS mode * @danger_safe_en: enable danger safe generation */ struct sde_hw_wb_qos_cfg { u32 danger_lut; u32 safe_lut; u64 creq_lut; + u32 bytes_per_clk; + enum sde_hw_wb_qos_mode qos_mode; bool danger_safe_en; }; diff --git a/msm/sde/sde_wb.c b/msm/sde/sde_wb.c index 741fd36b40..8bd5d3a37c 100644 --- a/msm/sde/sde_wb.c +++ b/msm/sde/sde_wb.c @@ -682,11 +682,15 @@ int sde_wb_connector_post_init(struct drm_connector *connector, void *display) msm_property_install_range(&c_conn->property_info, "dnsc_blur", 0x0, 0, ~0, 0, CONNECTOR_PROP_DNSC_BLUR); - if (wb_dev->wb_cfg->features & BIT(SDE_WB_LINEAR_ROTATION)) + if (wb_dev->wb_cfg->features & BIT(SDE_WB_LINEAR_ROTATION)) { msm_property_install_enum(&c_conn->property_info, "wb_rotate_type", 0x0, 0, e_wb_rotate_type, ARRAY_SIZE(e_wb_rotate_type), 0, CONNECTOR_PROP_WB_ROT_TYPE); + msm_property_install_range(&c_conn->property_info, "wb_rot_bytes_per_clk", + 0x0, 0, UINT_MAX, 0, CONNECTOR_PROP_WB_ROT_BYTES_PER_CLK); + } + msm_property_install_enum(&c_conn->property_info, "wb_usage_type", 0x0, 0, e_wb_usage_type, ARRAY_SIZE(e_wb_usage_type), 0, CONNECTOR_PROP_WB_USAGE_TYPE);