diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_ctl.c | 80 |
1 files changed, 75 insertions, 5 deletions
diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c index f44ebaf2cdac..d1595b33ba93 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c +++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c @@ -24,7 +24,10 @@ #define MDSS_MDP_BUS_FACTOR_SHIFT 10 /* 1.5 bus fudge factor */ #define MDSS_MDP_BUS_FUDGE_FACTOR_IB(val) (((val) / 2) * 3) +#define MDSS_MDP_BUS_FUDGE_FACTOR_HIGH_IB(val) (val << 1) #define MDSS_MDP_BUS_FUDGE_FACTOR_AB(val) (val << 1) +#define MDSS_MDP_BUS_FLOOR_BW (3200000000ULL >> MDSS_MDP_BUS_FACTOR_SHIFT) + /* 1.25 clock fudge factor */ #define MDSS_MDP_CLK_FUDGE_FACTOR(val) (((val) * 5) / 4) @@ -58,6 +61,74 @@ static inline u32 mdss_mdp_get_pclk_rate(struct mdss_mdp_ctl *ctl) pinfo->clk_rate; } +static u32 __mdss_mdp_ctrl_perf_ovrd_helper(struct mdss_mdp_mixer *mixer, + u32 *npipe) +{ + struct mdss_panel_info *pinfo; + struct mdss_mdp_pipe *pipe; + u32 mnum, ovrd = 0; + + if (!mixer || !mixer->ctl->panel_data) + return 0; + + pinfo = &mixer->ctl->panel_data->panel_info; + for (mnum = 0; mnum < MDSS_MDP_MAX_STAGE; mnum++) { + pipe = mixer->stage_pipe[mnum]; + if (pipe && pinfo) { + *npipe = *npipe + 1; + if ((pipe->src.w >= pipe->src.h) && + (pipe->src.w >= pinfo->xres)) + ovrd = 1; + } + } + + return ovrd; +} + +/** + * mdss_mdp_ctrl_perf_ovrd() - Determines if performance override is needed + * @mdata: Struct containing references to all MDP5 hardware structures + * and status info such as interupts, target caps etc. + * @ab_quota: Arbitrated bandwidth quota + * @ib_quota: Instantaneous bandwidth quota + * + * Function calculates the minimum required MDP and BIMC clocks to avoid MDP + * underflow during portrait video playback. The calculations are based on the + * way MDP fetches (bandwidth requirement) and processes data through + * MDP pipeline (MDP clock requirement) based on frame size and scaling + * requirements. + */ +static void __mdss_mdp_ctrl_perf_ovrd(struct mdss_data_type *mdata, + u64 *ab_quota, u64 *ib_quota) +{ + struct mdss_mdp_ctl *ctl; + u32 i, npipe = 0, ovrd = 0; + + for (i = 0; i < mdata->nctl; i++) { + ctl = mdata->ctl_off + i; + if (!ctl->power_on) + continue; + ovrd |= __mdss_mdp_ctrl_perf_ovrd_helper( + ctl->mixer_left, &npipe); + ovrd |= __mdss_mdp_ctrl_perf_ovrd_helper( + ctl->mixer_right, &npipe); + } + + *ab_quota = MDSS_MDP_BUS_FUDGE_FACTOR_AB(*ab_quota); + if (npipe > 1) + *ib_quota = MDSS_MDP_BUS_FUDGE_FACTOR_HIGH_IB(*ib_quota); + else + *ib_quota = MDSS_MDP_BUS_FUDGE_FACTOR_IB(*ib_quota); + + if (ovrd && (*ib_quota < MDSS_MDP_BUS_FLOOR_BW)) { + *ib_quota = MDSS_MDP_BUS_FLOOR_BW; + pr_debug("forcing the BIMC clock to 200 MHz : %llu bytes", + *ib_quota); + } else { + pr_debug("ib quota : %llu bytes", *ib_quota); + } +} + static int mdss_mdp_ctl_perf_commit(struct mdss_data_type *mdata, u32 flags) { struct mdss_mdp_ctl *ctl; @@ -82,16 +153,15 @@ static int mdss_mdp_ctl_perf_commit(struct mdss_data_type *mdata, u32 flags) } } if (flags & MDSS_MDP_PERF_UPDATE_BUS) { - bus_ab_quota = bus_ib_quota << MDSS_MDP_BUS_FACTOR_SHIFT; - bus_ab_quota = MDSS_MDP_BUS_FUDGE_FACTOR_AB(bus_ab_quota); - bus_ib_quota = MDSS_MDP_BUS_FUDGE_FACTOR_IB(bus_ib_quota); + bus_ab_quota = bus_ib_quota; + __mdss_mdp_ctrl_perf_ovrd(mdata, &bus_ab_quota, &bus_ib_quota); bus_ib_quota <<= MDSS_MDP_BUS_FACTOR_SHIFT; - + bus_ab_quota <<= MDSS_MDP_BUS_FACTOR_SHIFT; mdss_mdp_bus_scale_set_quota(bus_ab_quota, bus_ib_quota); } if (flags & MDSS_MDP_PERF_UPDATE_CLK) { clk_rate = MDSS_MDP_CLK_FUDGE_FACTOR(clk_rate); - pr_debug("update clk rate = %lu\n", clk_rate); + pr_debug("update clk rate = %lu HZ\n", clk_rate); mdss_mdp_set_clk_rate(clk_rate); } mutex_unlock(&mdss_mdp_ctl_lock); |
