From 6c700903fcf9dddca9a9af57dadbbe24c9ee683f Mon Sep 17 00:00:00 2001 From: Benjamin Chan Date: Mon, 26 Sep 2016 12:10:06 -0400 Subject: [PATCH] msm: sde: Adjust SDE rotator clock and BW calculation Optimize the initial rotator session opening time by moving the clock and BW voting to the start of rotator. Also adjusting the clock calcuation to include overhead and fudge factor. Create debugfs entry for supporting override the clock and BW calculation CRs-Fixed: 1071288 Change-Id: Ia6a84f160d0288ced98bf9f1818d9eabfc2e3963 Signed-off-by: Benjamin Chan --- .../msm/sde/rotator/sde_rotator_core.c | 114 ++++++++++++++---- .../msm/sde/rotator/sde_rotator_core.h | 2 + .../msm/sde/rotator/sde_rotator_debug.c | 34 ++++++ .../msm/sde/rotator/sde_rotator_dev.c | 33 +---- .../msm/sde/rotator/sde_rotator_dev.h | 7 ++ 5 files changed, 135 insertions(+), 55 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 041a8219e145..594bac6c5902 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c @@ -41,8 +41,12 @@ #define ROT_HW_ACQUIRE_TIMEOUT_IN_MS 100 /* default pixel per clock ratio */ -#define ROT_PIXEL_PER_CLK_NUMERATOR 4 -#define ROT_PIXEL_PER_CLK_DENOMINATOR 1 +#define ROT_PIXEL_PER_CLK_NUMERATOR 36 +#define ROT_PIXEL_PER_CLK_DENOMINATOR 10 +#define ROT_FUDGE_FACTOR_NUMERATOR 105 +#define ROT_FUDGE_FACTOR_DENOMINATOR 100 +#define ROT_OVERHEAD_NUMERATOR 27 +#define ROT_OVERHEAD_DENOMINATOR 10000 /* * Max rotator hw blocks possible. Used for upper array limits instead of @@ -998,12 +1002,33 @@ static u32 sde_rotator_calc_buf_bw(struct sde_mdp_format_params *fmt, return bw; } +static int sde_rotator_find_max_fps(struct sde_rot_mgr *mgr) +{ + struct sde_rot_file_private *priv; + struct sde_rot_perf *perf; + int max_fps = 0; + + list_for_each_entry(priv, &mgr->file_list, list) { + list_for_each_entry(perf, &priv->perf_list, list) { + if (perf->config.frame_rate > max_fps) + max_fps = perf->config.frame_rate; + } + } + + SDEROT_DBG("Max fps:%d\n", max_fps); + return max_fps; +} + static int sde_rotator_calc_perf(struct sde_rot_mgr *mgr, struct sde_rot_perf *perf) { struct sde_rotation_config *config = &perf->config; u32 read_bw, write_bw; struct sde_mdp_format_params *in_fmt, *out_fmt; + struct sde_rotator_device *rot_dev; + int max_fps; + + rot_dev = platform_get_drvdata(mgr->pdev); in_fmt = sde_get_format_params(config->input.format); if (!in_fmt) { @@ -1016,17 +1041,44 @@ static int sde_rotator_calc_perf(struct sde_rot_mgr *mgr, return -EINVAL; } + /* + * rotator processes 4 pixels per clock, but the actual throughtput + * is 3.6. We also need to take into account for overhead time. Final + * equation is: + * W x H / throughput / (1/fps - overhead) * fudge_factor + */ + max_fps = sde_rotator_find_max_fps(mgr); perf->clk_rate = config->input.width * config->input.height; - perf->clk_rate *= config->frame_rate; - /* rotator processes 4 pixels per clock */ perf->clk_rate = (perf->clk_rate * mgr->pixel_per_clk.denom) / mgr->pixel_per_clk.numer; + perf->clk_rate *= max_fps; + perf->clk_rate = (perf->clk_rate * mgr->fudge_factor.numer) / + mgr->fudge_factor.denom; + perf->clk_rate *= mgr->overhead.denom; + + /* + * check for override overhead default value + */ + if (rot_dev->min_overhead_us > (mgr->overhead.numer * 100)) + perf->clk_rate = DIV_ROUND_UP_ULL(perf->clk_rate, + (mgr->overhead.denom - max_fps * + (rot_dev->min_overhead_us / 100))); + else + perf->clk_rate = DIV_ROUND_UP_ULL(perf->clk_rate, + (mgr->overhead.denom - max_fps * + mgr->overhead.numer)); + + /* + * check for Override clock calcualtion + */ + if (rot_dev->min_rot_clk > perf->clk_rate) + perf->clk_rate = rot_dev->min_rot_clk; read_bw = sde_rotator_calc_buf_bw(in_fmt, config->input.width, - config->input.height, config->frame_rate); + config->input.height, max_fps); write_bw = sde_rotator_calc_buf_bw(out_fmt, config->output.width, - config->output.height, config->frame_rate); + config->output.height, max_fps); read_bw = sde_apply_comp_ratio_factor(read_bw, in_fmt, &config->input.comp_ratio); @@ -1035,13 +1087,22 @@ static int sde_rotator_calc_perf(struct sde_rot_mgr *mgr, perf->bw = read_bw + write_bw; + /* + * check for override bw calculation + */ + if (rot_dev->min_bw > perf->bw) + perf->bw = rot_dev->min_bw; + perf->rdot_limit = sde_mdp_get_ot_limit( config->input.width, config->input.height, - config->input.format, config->frame_rate, true); + config->input.format, max_fps, true); perf->wrot_limit = sde_mdp_get_ot_limit( config->input.width, config->input.height, - config->input.format, config->frame_rate, false); + config->input.format, max_fps, false); + SDEROT_DBG("clk:%lu, rdBW:%d, wrBW:%d, rdOT:%d, wrOT:%d\n", + perf->clk_rate, read_bw, write_bw, perf->rdot_limit, + perf->wrot_limit); return 0; } @@ -1747,16 +1808,9 @@ static int sde_rotator_open_session(struct sde_rot_mgr *mgr, config.session_id = session_id; perf->config = config; - perf->last_wb_idx = -1; + perf->last_wb_idx = 0; INIT_LIST_HEAD(&perf->list); - - ret = sde_rotator_calc_perf(mgr, perf); - if (ret) { - SDEROT_ERR("error setting the session %d\n", ret); - goto copy_user_err; - } - list_add(&perf->list, &private->perf_list); ret = sde_rotator_resource_ctrl(mgr, true); @@ -1777,25 +1831,17 @@ static int sde_rotator_open_session(struct sde_rot_mgr *mgr, goto enable_clk_err; } - ret = sde_rotator_update_perf(mgr); - if (ret) { - SDEROT_ERR("fail to open session, not enough clk/bw\n"); - goto perf_err; - } SDEROT_DBG("open session id=%u in{%u,%u}f:%u out{%u,%u}f:%u\n", config.session_id, config.input.width, config.input.height, config.input.format, config.output.width, config.output.height, config.output.format); goto done; -perf_err: - sde_rotator_clk_ctrl(mgr, false); enable_clk_err: update_clk_err: sde_rotator_resource_ctrl(mgr, false); resource_err: list_del_init(&perf->list); -copy_user_err: devm_kfree(&mgr->pdev->dev, perf->work_distribution); alloc_err: devm_kfree(&mgr->pdev->dev, perf); @@ -1867,11 +1913,23 @@ static int sde_rotator_config_session(struct sde_rot_mgr *mgr, } ret = sde_rotator_update_perf(mgr); + if (ret) { + SDEROT_ERR("error in updating perf: %d\n", ret); + goto done; + } - SDEROT_DBG("reconfig session id=%u in{%u,%u}f:%u out{%u,%u}f:%u\n", + ret = sde_rotator_update_clk(mgr); + if (ret) { + SDEROT_ERR("error in updating the rotator clk: %d\n", ret); + goto done; + } + + SDEROT_DBG( + "reconfig session id=%u in{%u,%u}f:%u out{%u,%u}f:%u fps:%d clk:%lu, bw:%llu\n", config->session_id, config->input.width, config->input.height, config->input.format, config->output.width, - config->output.height, config->output.format); + config->output.height, config->output.format, + config->frame_rate, perf->clk_rate, perf->bw); done: return ret; } @@ -2386,6 +2444,10 @@ int sde_rotator_core_init(struct sde_rot_mgr **pmgr, mgr->queue_count = 1; mgr->pixel_per_clk.numer = ROT_PIXEL_PER_CLK_NUMERATOR; mgr->pixel_per_clk.denom = ROT_PIXEL_PER_CLK_DENOMINATOR; + mgr->fudge_factor.numer = ROT_FUDGE_FACTOR_NUMERATOR; + mgr->fudge_factor.denom = ROT_FUDGE_FACTOR_DENOMINATOR; + mgr->overhead.numer = ROT_OVERHEAD_NUMERATOR; + mgr->overhead.denom = ROT_OVERHEAD_DENOMINATOR; mutex_init(&mgr->lock); atomic_set(&mgr->device_suspended, 0); diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h index aa17341de7c2..781b03e1b974 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h @@ -281,6 +281,8 @@ struct sde_rot_mgr { u32 hwacquire_timeout; struct sde_mult_factor pixel_per_clk; + struct sde_mult_factor fudge_factor; + struct sde_mult_factor overhead; int (*ops_config_hw)(struct sde_rot_hw_resource *hw, struct sde_rot_entry *entry); diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c index c609dbd2036e..94223b557990 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c @@ -914,6 +914,34 @@ static int sde_rotator_evtlog_create_debugfs( return 0; } + +static int sde_rotator_perf_create_debugfs( + struct sde_rotator_device *rot_dev, + struct dentry *debugfs_root) +{ + rot_dev->perf_root = debugfs_create_dir("perf", debugfs_root); + if (IS_ERR_OR_NULL(rot_dev->perf_root)) { + pr_err("debugfs_create_dir for perf failed, error %ld\n", + PTR_ERR(rot_dev->perf_root)); + rot_dev->perf_root = NULL; + return -ENODEV; + } + + rot_dev->min_rot_clk = 0; + debugfs_create_u32("min_rot_clk", S_IRUGO | S_IWUSR, + rot_dev->perf_root, &rot_dev->min_rot_clk); + + rot_dev->min_bw = 0; + debugfs_create_u32("min_bw", S_IRUGO | S_IWUSR, + rot_dev->perf_root, &rot_dev->min_bw); + + rot_dev->min_overhead_us = 0; + debugfs_create_u32("min_overhead_us", S_IRUGO | S_IWUSR, + rot_dev->perf_root, &rot_dev->min_overhead_us); + + return 0; +} + /* * struct sde_rotator_stat_ops - processed statistics file operations */ @@ -1006,6 +1034,12 @@ struct dentry *sde_rotator_create_debugfs( return NULL; } + if (sde_rotator_perf_create_debugfs(rot_dev, debugfs_root)) { + SDEROT_ERR("fail create perf debugfs\n"); + debugfs_remove_recursive(debugfs_root); + return NULL; + } + return debugfs_root; } diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c index d34623a531ba..930b18abd71b 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c @@ -546,22 +546,8 @@ static struct vb2_mem_ops sde_rotator_vb2_mem_ops = { static int sde_rotator_s_ctx_ctrl(struct sde_rotator_ctx *ctx, s32 *ctx_ctrl, struct v4l2_ctrl *ctrl) { - struct sde_rotator_device *rot_dev = ctx->rot_dev; - struct sde_rotation_config config; - s32 prev_val; - int ret; - - prev_val = *ctx_ctrl; *ctx_ctrl = ctrl->val; - sde_rotator_get_config_from_ctx(ctx, &config); - ret = sde_rotator_session_config(rot_dev->mgr, ctx->private, &config); - if (ret) { - SDEDEV_WARN(rot_dev->dev, "fail %s:%d s:%d\n", - ctrl->name, ctrl->val, ctx->session_id); - *ctx_ctrl = prev_val; - } - - return ret; + return 0; } /* @@ -1213,7 +1199,6 @@ static int sde_rotator_s_fmt_vid_cap(struct file *file, { struct sde_rotator_ctx *ctx = sde_rotator_ctx_from_fh(fh); struct sde_rotator_device *rot_dev = ctx->rot_dev; - struct sde_rotation_config config; int ret; ret = sde_rotator_try_fmt_vid_cap(file, fh, f); @@ -1235,12 +1220,6 @@ static int sde_rotator_s_fmt_vid_cap(struct file *file, f->fmt.pix.field, f->fmt.pix.width, f->fmt.pix.height); - /* configure hal to current input/output setting */ - sde_rot_mgr_lock(rot_dev->mgr); - sde_rotator_get_config_from_ctx(ctx, &config); - sde_rotator_session_config(rot_dev->mgr, ctx->private, &config); - sde_rot_mgr_unlock(rot_dev->mgr); - return 0; } @@ -1524,7 +1503,6 @@ static int sde_rotator_s_crop(struct file *file, void *fh, { struct sde_rotator_ctx *ctx = sde_rotator_ctx_from_fh(fh); struct sde_rotator_device *rot_dev = ctx->rot_dev; - struct sde_rotation_config config; struct sde_rotation_item item; struct v4l2_rect rect; @@ -1597,12 +1575,6 @@ static int sde_rotator_s_crop(struct file *file, void *fh, return -EINVAL; } - /* configure hal to current input/output setting */ - sde_rot_mgr_lock(rot_dev->mgr); - sde_rotator_get_config_from_ctx(ctx, &config); - sde_rotator_session_config(rot_dev->mgr, ctx->private, &config); - sde_rot_mgr_unlock(rot_dev->mgr); - return 0; } @@ -2336,6 +2308,9 @@ static int sde_rotator_probe(struct platform_device *pdev) rot_dev->early_submit = SDE_ROTATOR_EARLY_SUBMIT; rot_dev->fence_timeout = SDE_ROTATOR_FENCE_TIMEOUT; rot_dev->streamoff_timeout = SDE_ROTATOR_STREAM_OFF_TIMEOUT; + rot_dev->min_rot_clk = 0; + rot_dev->min_bw = 0; + rot_dev->min_overhead_us = 0; rot_dev->drvdata = sde_rotator_get_drv_data(&pdev->dev); rot_dev->pdev = pdev; diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.h index fd247d10128c..f3c904817296 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.h +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.h @@ -160,6 +160,9 @@ struct sde_rotator_statistics { * @session_id: Next context session identifier * @fence_timeout: Timeout value in msec for fence wait * @streamoff_timeout: Timeout value in msec for stream off + * @min_rot_clk: Override the minimum rotator clock from perf calculation + * @min_bw: Override the minimum bandwidth from perf calculation + * @min_overhead_us: Override the minimum overhead in us from perf calculation * @debugfs_root: Pointer to debugfs directory entry. * @stats: placeholder for rotator statistics */ @@ -177,8 +180,12 @@ struct sde_rotator_device { u32 session_id; u32 fence_timeout; u32 streamoff_timeout; + u32 min_rot_clk; + u32 min_bw; + u32 min_overhead_us; struct sde_rotator_statistics stats; struct dentry *debugfs_root; + struct dentry *perf_root; }; static inline