summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_ctl.c80
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);