msm: mdss: refactor ot limits to support rd and wr

Current code only supports to configure the same
read and write ot limits. For newer platforms it is
needed to configure different default limits for
each of the operations. This patch refactors the
implementation so the driver can support a different
default limit for the read and the write operations.

Change-Id: Ie54e4f24d52a561a6bf10de65ab6bce8a98211bb
Signed-off-by: Ingrid Gallardo <ingridg@codeaurora.org>
(cherry picked from commit 1b032907f97620955e76cfd0c7a970dd1d697db2)
[veeras@codeaurora.org: Resolve merge conflict in mdss.h, mdss-mdp.txt]
Signed-off-by: Veera Sundaram Sankaran <veeras@codeaurora.org>
This commit is contained in:
Ingrid Gallardo 2015-02-05 22:27:16 -08:00 committed by David Keitel
parent a07a798f71
commit 6bbba6f01f
6 changed files with 87 additions and 80 deletions

View file

@ -332,14 +332,23 @@ Optional properties:
sw_reset register bitmap. Number of offsets
defined should match the number of offsets
defined in property: qcom,mdss-pipe-dma-off
- qcom,mdss-rotator-ot-limit: This integer value indicates maximum number of pending
writes that can be allowed from rotator client. Default
value is 16 which is the maximum. This value can be
used to reduce the pending writes limit dynamically
and can be tuned to match performance requirements
depending upon system state.
- qcom,mdss-default-ot-limit: This integer value indicates the default number of pending
- qcom,mdss-default-ot-wr-limit: This integer value indicates maximum number of pending
writes that can be allowed from non real time client.
This value can be used to reduce the pending writes
limit and can be tuned to match performance
requirements depending upon system state.
Some platforms require a dynamic ot limiting in
some cases. Setting this default ot write limit
will enable this dynamic limiting for the write
operations in the platforms that require these
limits.
- qcom,mdss-default-ot-rd-limit: This integer value indicates the default number of pending
reads that can be allowed for the real time clients.
Some platforms require a dynamic ot limiting in
some cases. Setting this default ot read limit
will enable this dynamic limiting for the read
operations in the platforms that require these
limits.
- qcom,mdss-default-pipe-qos-lut: This value is used to program the default qos lut
register for the rt clients and nrt rotator read clients.
- qcom,mdss-clk-levels: This array indicates the mdp core clock level selection

View file

@ -251,9 +251,10 @@ struct mdss_data_type {
bool has_pixel_ram;
bool needs_hist_vote;
u32 rotator_ot_limit;
u32 default_ot_limit;
u32 default_ot_rd_limit;
u32 default_ot_wr_limit;
u32 default_pipe_qos_lut;
u32 mdp_irq_mask;
u32 mdp_hist_irq_mask;

View file

@ -2706,12 +2706,12 @@ static int mdss_mdp_parse_dt_misc(struct platform_device *pdev)
mdata->rot_block_size = (!rc ? data : 128);
rc = of_property_read_u32(pdev->dev.of_node,
"qcom,mdss-rotator-ot-limit", &data);
mdata->rotator_ot_limit = (!rc ? data : 0);
"qcom,mdss-default-ot-rd-limit", &data);
mdata->default_ot_rd_limit = (!rc ? data : 0);
rc = of_property_read_u32(pdev->dev.of_node,
"qcom,mdss-default-ot-limit", &data);
mdata->default_ot_limit = (!rc ? data : 0);
"qcom,mdss-default-ot-wr-limit", &data);
mdata->default_ot_wr_limit = (!rc ? data : 0);
rc = of_property_read_u32(pdev->dev.of_node,
"qcom,mdss-default-pipe-qos-lut", &data);
@ -3155,39 +3155,59 @@ bool force_on_xin_clk(u32 bit_off, u32 clk_ctl_reg_off, bool enable)
return clk_forced_on;
}
static bool limit_rotator_ot(bool is_yuv, u32 width, u32 height)
{
return (true == is_yuv) &&
(width * height <= 1080 * 1920);
}
static int limit_wb_ot(u32 width, u32 height)
{
return width * height <= 1080 * 1920;
}
static u32 get_ot_limit(u32 reg_off, u32 bit_off, bool is_rot,
bool is_wb, bool is_yuv, u32 width, u32 height)
static void apply_dynamic_ot_limit(u32 *ot_lim,
struct mdss_mdp_set_ot_params *params)
{
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
u32 ot_lim = mdata->default_ot_limit;
u32 res;
if (!is_dynamic_ot_limit_required(mdata->mdp_rev))
return;
res = params->width * params->height;
pr_debug("w:%d h:%d rot:%d yuv:%d wb:%d res:%d\n",
params->width, params->height, params->is_rot,
params->is_yuv, params->is_wb, res);
if ((params->is_rot && params->is_yuv) ||
params->is_wb) {
if (res <= 1080 * 1920) {
*ot_lim = 2;
} else if (res <= 3840 * 2160) {
if (params->is_rot && params->is_yuv)
*ot_lim = 8;
else
*ot_lim = 16;
}
}
}
static u32 get_ot_limit(u32 reg_off, u32 bit_off,
struct mdss_mdp_set_ot_params *params)
{
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
u32 ot_lim = 0;
u32 is_vbif_nrt, val;
if (mdata->default_ot_wr_limit &&
(params->reg_off_vbif_lim_conf == MMSS_VBIF_WR_LIM_CONF))
ot_lim = mdata->default_ot_wr_limit;
else if (mdata->default_ot_rd_limit &&
(params->reg_off_vbif_lim_conf == MMSS_VBIF_RD_LIM_CONF))
ot_lim = mdata->default_ot_rd_limit;
/*
* If default ot limit is not set from dt,
* then ot limiting is disabled.
* If default ot is not set from dt,
* then do not configure it.
*/
if (ot_lim == 0)
goto exit;
/* Modify the limits if the target and the use case requires it */
apply_dynamic_ot_limit(&ot_lim, params);
is_vbif_nrt = mdss_mdp_is_vbif_nrt(mdata->mdp_rev);
if ((is_rot && limit_rotator_ot(is_yuv, width, height)) ||
(is_wb && limit_wb_ot(width, height))) {
ot_lim = MDSS_OT_LIMIT;
}
val = MDSS_VBIF_READ(mdata, reg_off, is_vbif_nrt);
val &= (0xFF << bit_off);
val = val >> bit_off;
@ -3196,11 +3216,11 @@ static u32 get_ot_limit(u32 reg_off, u32 bit_off, bool is_rot,
ot_lim = 0;
exit:
pr_debug("ot_lim=%d\n", ot_lim);
return ot_lim;
}
void mdss_mdp_set_ot_limit(struct mdss_mdp_set_ot_params *params,
bool is_rot, bool is_wb, bool is_yuv)
void mdss_mdp_set_ot_limit(struct mdss_mdp_set_ot_params *params)
{
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
u32 ot_lim;
@ -3211,15 +3231,10 @@ void mdss_mdp_set_ot_limit(struct mdss_mdp_set_ot_params *params,
u32 reg_val;
bool forced_on;
if (!mdss_mdp_apply_ot_limit(mdata->mdp_rev))
goto exit;
ot_lim = get_ot_limit(
reg_off_vbif_lim_conf,
bit_off_vbif_lim_conf,
is_rot, is_wb, is_yuv,
params->width,
params->height) & 0xFF;
params) & 0xFF;
if (ot_lim == 0)
goto exit;

View file

@ -83,12 +83,6 @@
#define MASTER_CTX 0
#define SLAVE_CTX 1
/*
* Recommendation is to have different ot depending on the fps
* and resolution, but since current SW doesn't support different
* fps for non-real time, we are hard-coding the ot limit to 2 for now
*/
#define MDSS_OT_LIMIT 2
#define XIN_HALT_TIMEOUT_US 0x4000
enum mdss_mdp_perf_state_type {
@ -601,6 +595,9 @@ struct mdss_mdp_set_ot_params {
u32 num;
u32 width;
u32 height;
bool is_rot;
bool is_wb;
bool is_yuv;
u32 reg_off_vbif_lim_conf;
u32 reg_off_mdp_clk_ctrl;
u32 bit_off_mdp_clk_ctrl;
@ -716,7 +713,7 @@ static inline bool mdss_mdp_is_vbif_nrt(u32 mdp_rev)
MDSS_MDP_HW_REV_107);
}
static inline bool mdss_mdp_apply_ot_limit(u32 mdp_rev)
static inline bool is_dynamic_ot_limit_required(u32 mdp_rev)
{
return mdp_rev == MDSS_MDP_HW_REV_105 ||
mdp_rev == MDSS_MDP_HW_REV_109 ||
@ -1150,8 +1147,7 @@ int mdss_mdp_wb_get_secure(struct msm_fb_data_type *mfd, uint8_t *enable);
void mdss_mdp_ctl_restore(void);
int mdss_mdp_ctl_reset(struct mdss_mdp_ctl *ctl);
int mdss_mdp_wait_for_xin_halt(u32 xin_id, bool is_vbif_nrt);
void mdss_mdp_set_ot_limit(struct mdss_mdp_set_ot_params *params,
bool is_rot, bool is_wb, bool is_yuv);
void mdss_mdp_set_ot_limit(struct mdss_mdp_set_ot_params *params);
int mdss_mdp_cmd_set_autorefresh_mode(struct mdss_mdp_ctl *ctl,
int frame_cnt);
int mdss_mdp_ctl_cmd_autorefresh_enable(struct mdss_mdp_ctl *ctl,

View file

@ -705,19 +705,20 @@ static void mdss_mdp_set_ot_limit_wb(struct mdss_mdp_writeback_ctx *ctx)
ot_params.reg_off_vbif_lim_conf = MMSS_VBIF_WR_LIM_CONF;
ot_params.reg_off_mdp_clk_ctrl = ctx->clk_ctrl.reg_off;
ot_params.bit_off_mdp_clk_ctrl = ctx->clk_ctrl.bit_off;
ot_params.is_rot = (ctx->type == MDSS_MDP_WRITEBACK_TYPE_ROTATOR);
ot_params.is_wb = (ctx->type == MDSS_MDP_WRITEBACK_TYPE_WFD) ||
(ctx->type == MDSS_MDP_WRITEBACK_TYPE_LINE);
ot_params.is_yuv = ctx->dst_fmt->is_yuv;
mdss_mdp_set_ot_limit(&ot_params);
mdss_mdp_set_ot_limit(&ot_params,
ctx->type == MDSS_MDP_WRITEBACK_TYPE_ROTATOR,
(ctx->type == MDSS_MDP_WRITEBACK_TYPE_WFD) ||
(ctx->type == MDSS_MDP_WRITEBACK_TYPE_LINE),
ctx->dst_fmt->is_yuv);
}
static int mdss_mdp_writeback_display(struct mdss_mdp_ctl *ctl, void *arg)
{
struct mdss_mdp_writeback_ctx *ctx;
struct mdss_mdp_writeback_arg *wb_args;
u32 flush_bits = 0, val, bit_off, reg_off;
u32 flush_bits = 0;
int ret;
if (!ctl || !ctl->mdata)
@ -733,24 +734,9 @@ static int mdss_mdp_writeback_display(struct mdss_mdp_ctl *ctl, void *arg)
return -EPERM;
}
if (ctl->mdata->rotator_ot_limit) {
if (ctx->type == MDSS_MDP_WRITEBACK_TYPE_ROTATOR)
ctx->wr_lim = ctl->mdata->rotator_ot_limit;
else
ctx->wr_lim = MDSS_DEFAULT_OT_SETTING;
reg_off = (ctx->xin_id / 4) * 4;
bit_off = (ctx->xin_id % 4) * 8;
val = MDSS_VBIF_READ(ctl->mdata, MMSS_VBIF_WR_LIM_CONF +
reg_off, ctx->is_vbif_nrt);
val &= ~(0xFF << bit_off);
val |= (ctx->wr_lim) << bit_off;
MDSS_VBIF_WRITE(ctl->mdata, MMSS_VBIF_WR_LIM_CONF + reg_off,
val, ctx->is_vbif_nrt);
} else {
if (ctl->mdata->default_ot_wr_limit ||
ctl->mdata->default_ot_rd_limit)
mdss_mdp_set_ot_limit_wb(ctx);
}
wb_args = (struct mdss_mdp_writeback_arg *) arg;
if (!wb_args)

View file

@ -1857,11 +1857,11 @@ static void mdss_mdp_set_ot_limit_pipe(struct mdss_mdp_pipe *pipe)
ot_params.reg_off_mdp_clk_ctrl = pipe->clk_ctrl.reg_off;
ot_params.bit_off_mdp_clk_ctrl = pipe->clk_ctrl.bit_off +
CLK_FORCE_ON_OFFSET;
ot_params.is_rot = pipe->mixer_left->rotator_mode;
ot_params.is_wb = ctl->intf_num == MDSS_MDP_NO_INTF;
ot_params.is_yuv = pipe->src_fmt->is_yuv;
mdss_mdp_set_ot_limit(&ot_params,
pipe->mixer_left->rotator_mode,
ctl->intf_num == MDSS_MDP_NO_INTF,
pipe->src_fmt->is_yuv);
mdss_mdp_set_ot_limit(&ot_params);
}
int mdss_mdp_pipe_queue_data(struct mdss_mdp_pipe *pipe,