diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2016-09-30 18:23:47 -0700 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2016-09-30 18:23:47 -0700 |
commit | 627381d09a60fdd30bb26fe3868afb8568b6b3ae (patch) | |
tree | 1e1fc5479324333593633ac86dd58d2bd2688c84 | |
parent | 789809fbfc27c82a643406d06a87da40aa2fbdbd (diff) | |
parent | 6c700903fcf9dddca9a9af57dadbbe24c9ee683f (diff) |
Merge "msm: sde: Adjust SDE rotator clock and BW calculation"
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; + } + + 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\n", + 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 |