From 8e761d5f6971c772a6fb197474014f1c0b78f836 Mon Sep 17 00:00:00 2001 From: Benjamin Chan Date: Wed, 21 Dec 2016 15:45:26 -0500 Subject: [PATCH 1/2] msm: sde: Enable traffic shaping for 4k@30fps rotation For 30fps rotation, it is only required to perform a commit every other vsync for a 60fps refresh rate panel. Rotation time for a 4k resolution will take approx 12ms including SW overhead, and leave very little room to perform a frame commit in fb driver. One way is to delay the rotation time by enabling traffic shaping for 4k@30fps content so that the it will take approx 15ms to finish, and that will force the frame commit into next vsync time slot and thus matching the cadence of 30fps commit time. CRs-Fixed: 1100633 Change-Id: I0aecfe767cd77140f75bb13c4fe6f9267d4d911e Signed-off-by: Benjamin Chan --- .../platform/msm/sde/rotator/sde_rotator_r3.c | 64 ++++++++++++++++++- .../msm/sde/rotator/sde_rotator_r3_internal.h | 7 +- 2 files changed, 67 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c index f2a9da737453..aa0aa6487b42 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -36,6 +36,12 @@ #include "sde_rotator_trace.h" #include "sde_rotator_debug.h" +#define RES_UHD (3840*2160) + +/* traffic shaping clock ticks = finish_time x 19.2MHz */ +#define TRAFFIC_SHAPE_CLKTICK_14MS 268800 +#define TRAFFIC_SHAPE_CLKTICK_12MS 230400 + /* XIN mapping */ #define XIN_SSPP 0 #define XIN_WRITEBACK 1 @@ -650,6 +656,20 @@ static void sde_hw_rotator_setup_fetchengine(struct sde_hw_rotator_context *ctx, ctx->is_secure = false; } + /* + * Determine if traffic shaping is required. Only enable traffic + * shaping when content is 4k@30fps. The actual traffic shaping + * bandwidth calculation is done in output setup. + */ + if (((cfg->src_rect->w * cfg->src_rect->h) >= RES_UHD) && + (cfg->fps <= 30)) { + SDEROT_DBG("Enable Traffic Shaper\n"); + ctx->is_traffic_shaping = true; + } else { + SDEROT_DBG("Disable Traffic Shaper\n"); + ctx->is_traffic_shaping = false; + } + /* Update command queue write ptr */ sde_hw_rotator_put_regdma_segment(ctx, wrptr); } @@ -762,6 +782,36 @@ static void sde_hw_rotator_setup_wbengine(struct sde_hw_rotator_context *ctx, else SDE_REGDMA_WRITE(wrptr, ROTTOP_OP_MODE, 0x1); + /* setup traffic shaper for 4k 30fps content */ + if (ctx->is_traffic_shaping) { + u32 bw; + + /* + * Target to finish in 12ms, and we need to set number of bytes + * per clock tick for traffic shaping. + * Each clock tick run @ 19.2MHz, so we need we know total of + * clock ticks in 14ms, i.e. 12ms/(1/19.2MHz) ==> 23040 + * Finally, calcualte the byte count per clock tick based on + * resolution, bpp and compression ratio. + */ + bw = cfg->dst_rect->w * cfg->dst_rect->h; + + if (fmt->chroma_sample == SDE_MDP_CHROMA_420) + bw = (bw * 3) / 2; + else + bw *= fmt->bpp; + + bw /= TRAFFIC_SHAPE_CLKTICK_12MS; + if (bw > 0xFF) + bw = 0xFF; + SDE_REGDMA_WRITE(wrptr, ROT_WB_TRAFFIC_SHAPER_WR_CLIENT, + BIT(31) | bw); + SDEROT_DBG("Enable ROT_WB Traffic Shaper:%d\n", bw); + } else { + SDE_REGDMA_WRITE(wrptr, ROT_WB_TRAFFIC_SHAPER_WR_CLIENT, 0); + SDEROT_DBG("Disable ROT_WB Traffic Shaper\n"); + } + /* Update command queue write ptr */ sde_hw_rotator_put_regdma_segment(ctx, wrptr); } @@ -1580,6 +1630,8 @@ static int sde_hw_rotator_config(struct sde_rot_hw_resource *hw, sspp_cfg.img_width = item->input.width; sspp_cfg.img_height = item->input.height; + sspp_cfg.fps = entry->perf->config.frame_rate; + sspp_cfg.bw = entry->perf->bw; sspp_cfg.fmt = sde_get_format_params(item->input.format); if (!sspp_cfg.fmt) { SDEROT_ERR("null format\n"); @@ -1599,6 +1651,8 @@ static int sde_hw_rotator_config(struct sde_rot_hw_resource *hw, wb_cfg.img_width = item->output.width; wb_cfg.img_height = item->output.height; + wb_cfg.fps = entry->perf->config.frame_rate; + wb_cfg.bw = entry->perf->bw; wb_cfg.fmt = sde_get_format_params(item->output.format); wb_cfg.dst_rect = &item->dst_rect; wb_cfg.data = &entry->dst_buf; @@ -1642,7 +1696,9 @@ static int sde_hw_rotator_config(struct sde_rot_hw_resource *hw, MMSS_VBIF_NRT_VBIF_CLK_FORCE_CTRL0; ot_params.bit_off_mdp_clk_ctrl = MMSS_VBIF_NRT_VBIF_CLK_FORCE_CTRL0_XIN0; - ot_params.fmt = entry->perf->config.input.format; + ot_params.fmt = ctx->is_traffic_shaping ? + SDE_PIX_FMT_ABGR_8888 : + entry->perf->config.input.format; sde_mdp_set_ot_limit(&ot_params); } @@ -1660,7 +1716,9 @@ static int sde_hw_rotator_config(struct sde_rot_hw_resource *hw, MMSS_VBIF_NRT_VBIF_CLK_FORCE_CTRL0; ot_params.bit_off_mdp_clk_ctrl = MMSS_VBIF_NRT_VBIF_CLK_FORCE_CTRL0_XIN1; - ot_params.fmt = entry->perf->config.input.format; + ot_params.fmt = ctx->is_traffic_shaping ? + SDE_PIX_FMT_ABGR_8888 : + entry->perf->config.input.format; sde_mdp_set_ot_limit(&ot_params); } diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h index e666f4811c77..5502cc09ae19 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -73,6 +73,8 @@ struct sde_hw_rot_sspp_cfg { struct sde_mdp_data *data; u32 img_width; u32 img_height; + u32 fps; + u64 bw; }; @@ -93,6 +95,8 @@ struct sde_hw_rot_wb_cfg { u32 img_height; u32 v_downscale_factor; u32 h_downscale_factor; + u32 fps; + u64 bw; }; @@ -214,6 +218,7 @@ struct sde_hw_rotator_context { u32 last_regdma_timestamp; dma_addr_t ts_addr; bool is_secure; + bool is_traffic_shaping; }; /** From e43aa01402fb8b97be2f51cafdc8d036e4253292 Mon Sep 17 00:00:00 2001 From: Benjamin Chan Date: Thu, 22 Dec 2016 18:42:34 -0500 Subject: [PATCH 2/2] msm: sde: Reduce SDE rotator done signaling time When rotator job finished, driver needs to send out done signaling to notify fbdev driver to perform a commit. However, there are occasions that the SMMU disabling take quite long time and delaying the fbdev commit time. To reduce this unpredict latency, move the SMMU disabling much later in the rotator done handling, and also remove unnecessary SMMU disabling call during commit phase. CRs-Fixed: 1100633 Change-Id: I76ad017661aa6f760a2adc3579f59a7b66ab8e40 Signed-off-by: Benjamin Chan --- .../platform/msm/sde/rotator/sde_rotator_core.c | 17 ++++++++++++++++- .../platform/msm/sde/rotator/sde_rotator_r3.c | 10 +--------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c index 2fc130137c25..920f5a809777 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1390,6 +1390,14 @@ static void sde_rotator_commit_handler(struct work_struct *work) entry->item.dst_rect.x, entry->item.dst_rect.y, entry->item.dst_rect.w, entry->item.dst_rect.h); + ATRACE_INT("sde_smmu_ctrl", 0); + ret = sde_smmu_ctrl(1); + if (IS_ERR_VALUE(ret)) { + SDEROT_ERR("IOMMU attach failed\n"); + goto smmu_error; + } + ATRACE_INT("sde_smmu_ctrl", 1); + ret = sde_rotator_map_and_check_data(entry); if (ret) { SDEROT_ERR("fail to prepare input/output data %d\n", ret); @@ -1415,6 +1423,8 @@ static void sde_rotator_commit_handler(struct work_struct *work) sde_rot_mgr_unlock(mgr); return; error: + sde_smmu_ctrl(0); +smmu_error: sde_rotator_put_hw_resource(entry->commitq, entry, hw); get_hw_res_err: sde_rotator_signal_output(entry); @@ -1491,6 +1501,7 @@ static void sde_rotator_done_handler(struct work_struct *work) sde_rot_mgr_lock(mgr); sde_rotator_put_hw_resource(entry->commitq, entry, entry->commitq->hw); sde_rotator_signal_output(entry); + ATRACE_INT("sde_rot_done", 1); sde_rotator_release_entry(mgr, entry); atomic_dec(&request->pending_count); if (request->retireq && request->retire_work) @@ -1498,6 +1509,10 @@ static void sde_rotator_done_handler(struct work_struct *work) if (entry->item.ts) entry->item.ts[SDE_ROTATOR_TS_RETIRE] = ktime_get(); sde_rot_mgr_unlock(mgr); + + ATRACE_INT("sde_smmu_ctrl", 3); + sde_smmu_ctrl(0); + ATRACE_INT("sde_smmu_ctrl", 4); } static bool sde_rotator_verify_format(struct sde_rot_mgr *mgr, diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c index aa0aa6487b42..ddf11b35a1d6 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c @@ -1089,6 +1089,7 @@ static u32 sde_hw_rotator_wait_done_regdma( !sde_hw_rotator_pending_swts(rot, ctx, &swts), KOFF_TIMEOUT); + ATRACE_INT("sde_rot_done", 0); spin_lock_irqsave(&rot->rotisr_lock, flags); last_isr = ctx->last_regdma_isr_status; @@ -1769,7 +1770,6 @@ static int sde_hw_rotator_kickoff(struct sde_rot_hw_resource *hw, struct sde_hw_rotator *rot; struct sde_hw_rotator_resource_info *resinfo; struct sde_hw_rotator_context *ctx; - int ret = 0; if (!hw || !entry) { SDEROT_ERR("null hw resource/entry\n"); @@ -1787,12 +1787,6 @@ static int sde_hw_rotator_kickoff(struct sde_rot_hw_resource *hw, return -EINVAL; } - ret = sde_smmu_ctrl(1); - if (IS_ERR_VALUE(ret)) { - SDEROT_ERR("IOMMU attach failed\n"); - return ret; - } - rot->ops.start_rotator(ctx, ctx->q_id); return 0; @@ -1832,8 +1826,6 @@ static int sde_hw_rotator_wait4done(struct sde_rot_hw_resource *hw, ret = rot->ops.wait_rotator_done(ctx, ctx->q_id, 0); - sde_smmu_ctrl(0); - if (rot->dbgmem) { sde_hw_rotator_unmap_vaddr(&ctx->src_dbgbuf); sde_hw_rotator_unmap_vaddr(&ctx->dst_dbgbuf);