diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h index f16e56c9a21a..def5f7f167fe 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.h +++ b/drivers/video/fbdev/msm/mdss_mdp.h @@ -69,6 +69,8 @@ #define PERF_CALC_PIPE_SINGLE_LAYER BIT(1) #define PERF_CALC_PIPE_CALC_SMP_SIZE BIT(2) +#define PERF_SINGLE_PIPE_BW_FLOOR 1200000000 + enum mdss_mdp_perf_state_type { PERF_SW_COMMIT_STATE = 0, PERF_HW_MDP_STATE, @@ -168,12 +170,18 @@ enum mdss_mdp_wb_ctl_type { MDSS_MDP_WB_CTL_TYPE_LINE }; +enum mdss_mdp_bw_vote_mode { + MDSS_MDP_BW_MODE_SINGLE_LAYER, + MDSS_MDP_BW_MODE_MAX +}; + struct mdss_mdp_perf_params { u64 bw_overlap; u64 bw_prefill; u32 prefill_bytes; u64 bw_ctl; u32 mdp_clk_rate; + DECLARE_BITMAP(bw_vote_mode, MDSS_MDP_BW_MODE_MAX); }; struct mdss_mdp_ctl { diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c index f6e8c09cca9e..ee5a902a7e96 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c +++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "mdss_fb.h" #include "mdss_mdp.h" @@ -421,6 +422,34 @@ u32 mdss_mdp_perf_calc_smp_size(struct mdss_mdp_pipe *pipe, return smp_bytes; } +static void mdss_mdp_get_bw_vote_mode(struct mdss_mdp_mixer *mixer, + u32 mdp_rev, struct mdss_mdp_perf_params *perf, u32 flags) +{ + bitmap_zero(perf->bw_vote_mode, MDSS_MDP_BW_MODE_MAX); + + if (!mixer) + goto exit; + + switch (mdp_rev) { + case MDSS_MDP_HW_REV_105: + case MDSS_MDP_HW_REV_109: + if ((flags & PERF_CALC_PIPE_SINGLE_LAYER) && + !mixer->rotator_mode && + (mixer->type == MDSS_MDP_MIXER_TYPE_INTF)) { + set_bit(MDSS_MDP_BW_MODE_SINGLE_LAYER, + perf->bw_vote_mode); + } + break; + default: + break; + }; + + pr_debug("mode=0x%lx\n", *(perf->bw_vote_mode)); + +exit: + return; +} + /** * mdss_mdp_perf_calc_pipe() - calculate performance numbers required by pipe * @pipe: Source pipe struct containing updated pipe params @@ -578,6 +607,8 @@ int mdss_mdp_perf_calc_pipe(struct mdss_mdp_pipe *pipe, prefill_params.is_cmd = !mixer->ctl->is_video_mode; prefill_params.pnum = pipe->num; + mdss_mdp_get_bw_vote_mode(mixer, mdata->mdp_rev, perf, flags); + if (flags & PERF_CALC_PIPE_SINGLE_LAYER) perf->prefill_bytes = mdss_mdp_perf_calc_pipe_prefill_single(&prefill_params); @@ -695,6 +726,9 @@ static void mdss_mdp_perf_calc_mixer(struct mdss_mdp_mixer *mixer, for (i = 0; i < num_pipes; i++) { struct mdss_mdp_perf_params tmp; + + memset(&tmp, 0, sizeof(tmp)); + pipe = pipe_list[i]; if (pipe == NULL) continue; @@ -711,6 +745,9 @@ static void mdss_mdp_perf_calc_mixer(struct mdss_mdp_mixer *mixer, flags)) continue; + bitmap_or(perf->bw_vote_mode, perf->bw_vote_mode, + tmp.bw_vote_mode, MDSS_MDP_BW_MODE_MAX); + prefill_bytes += tmp.prefill_bytes; bw_overlap[i] = tmp.bw_overlap; v_region[2*i] = pipe->dst.y; @@ -757,9 +794,10 @@ static void mdss_mdp_perf_calc_mixer(struct mdss_mdp_mixer *mixer, perf->mdp_clk_rate = max_clk_rate; exit: - pr_debug("final mixer=%d video=%d clk_rate=%u bw=%llu prefill=%d\n", + pr_debug("final mixer=%d video=%d clk_rate=%u bw=%llu prefill=%d mode=0x%lx\n", mixer->num, mixer->ctl->is_video_mode, perf->mdp_clk_rate, - perf->bw_overlap, perf->prefill_bytes); + perf->bw_overlap, perf->prefill_bytes, + *(perf->bw_vote_mode)); } static u32 mdss_mdp_get_vbp_factor(struct mdss_mdp_ctl *ctl) @@ -841,6 +879,10 @@ static void __mdss_mdp_perf_calc_ctl_helper(struct mdss_mdp_ctl *ctl, if (ctl->mixer_left) { mdss_mdp_perf_calc_mixer(ctl->mixer_left, &tmp, left_plist, left_cnt, flags); + + bitmap_or(perf->bw_vote_mode, perf->bw_vote_mode, + tmp.bw_vote_mode, MDSS_MDP_BW_MODE_MAX); + perf->bw_overlap += tmp.bw_overlap; perf->prefill_bytes += tmp.prefill_bytes; perf->mdp_clk_rate = tmp.mdp_clk_rate; @@ -849,6 +891,10 @@ static void __mdss_mdp_perf_calc_ctl_helper(struct mdss_mdp_ctl *ctl, if (ctl->mixer_right) { mdss_mdp_perf_calc_mixer(ctl->mixer_right, &tmp, right_plist, right_cnt, flags); + + bitmap_or(perf->bw_vote_mode, perf->bw_vote_mode, + tmp.bw_vote_mode, MDSS_MDP_BW_MODE_MAX); + perf->bw_overlap += tmp.bw_overlap; perf->prefill_bytes += tmp.prefill_bytes; if (tmp.mdp_clk_rate > perf->mdp_clk_rate) @@ -882,8 +928,9 @@ static void __mdss_mdp_perf_calc_ctl_helper(struct mdss_mdp_ctl *ctl, } perf->bw_ctl = max(perf->bw_prefill, perf->bw_overlap); - pr_debug("ctl=%d, prefill bw=%llu, overlap bw=%llu\n", - ctl->num, perf->bw_prefill, perf->bw_overlap); + pr_debug("ctl=%d prefill bw=%llu overlap bw=%llu mode=0x%lx\n", + ctl->num, perf->bw_prefill, perf->bw_overlap, + *(perf->bw_vote_mode)); } int mdss_mdp_perf_bw_check(struct mdss_mdp_ctl *ctl, @@ -1125,6 +1172,8 @@ static inline void mdss_mdp_ctl_perf_update_bus(struct mdss_data_type *mdata, u64 bw_sum_of_intfs_rt = 0, bw_sum_of_intfs_nrt = 0; u64 bus_ab_quota_rt, bus_ab_quota_nrt, bus_ib_quota; int i; + struct mdss_mdp_perf_params perf_temp; + bitmap_zero(perf_temp.bw_vote_mode, MDSS_MDP_BW_MODE_MAX); ATRACE_BEGIN(__func__); for (i = 0; i < mdata->nctl; i++) { @@ -1139,6 +1188,13 @@ static inline void mdss_mdp_ctl_perf_update_bus(struct mdss_data_type *mdata, if (ctl->traffic_shaper_enabled) mdss_mdp_ctl_perf_update_traffic_shaper_bw (ctl, mdp_clk); + + if (ctl->cur_perf.bw_vote_mode) + bitmap_or(perf_temp.bw_vote_mode, + perf_temp.bw_vote_mode, + ctl->cur_perf.bw_vote_mode, + MDSS_MDP_BW_MODE_MAX); + mixer = ctl->mixer_left; if (ctl->intf_num == MDSS_MDP_NO_INTF || mixer->rotator_mode) @@ -1146,19 +1202,31 @@ static inline void mdss_mdp_ctl_perf_update_bus(struct mdss_data_type *mdata, else bw_sum_of_intfs_rt += ctl->cur_perf.bw_ctl; - pr_debug("ctl_num=%d bw=%llu\n", ctl->num, - ctl->cur_perf.bw_ctl); + pr_debug("ctl_num=%d bw=%llu mode=0x%lx\n", ctl->num, + ctl->cur_perf.bw_ctl, + *(ctl->cur_perf.bw_vote_mode)); } } bw_sum_of_intfs_rt = max(bw_sum_of_intfs_rt, mdata->perf_tune.min_bus_vote); + bus_ib_quota = bw_sum_of_intfs_rt + bw_sum_of_intfs_nrt; + if (test_bit(MDSS_MDP_BW_MODE_SINGLE_LAYER, + perf_temp.bw_vote_mode) && + (bus_ib_quota >= PERF_SINGLE_PIPE_BW_FLOOR)) { + struct mdss_fudge_factor ib_factor_vscaling; + ib_factor_vscaling.numer = 2; + ib_factor_vscaling.denom = 1; + bus_ib_quota = apply_fudge_factor(bus_ib_quota, + &ib_factor_vscaling); + } + bus_ab_quota_rt = apply_fudge_factor(bw_sum_of_intfs_rt, &mdss_res->ab_factor); bus_ab_quota_nrt = apply_fudge_factor(bw_sum_of_intfs_nrt, &mdss_res->ab_factor); - trace_mdp_perf_update_bus(bus_ab_quota_rt, bus_ab_quota_nrt - , bus_ib_quota); + trace_mdp_perf_update_bus(bus_ab_quota_rt, bus_ab_quota_nrt, + bus_ib_quota, *(perf_temp.bw_vote_mode)); ATRACE_INT("bus_quota", bus_ib_quota); mdss_bus_scale_set_quota(MDSS_HW_MDP, bus_ab_quota_rt, bus_ab_quota_nrt , bus_ib_quota); @@ -1322,6 +1390,8 @@ static void mdss_mdp_ctl_perf_update(struct mdss_mdp_ctl *ctl, ctl->num, params_changed, new->bw_ctl, old->bw_ctl); old->bw_ctl = new->bw_ctl; + bitmap_copy(old->bw_vote_mode, new->bw_vote_mode, + MDSS_MDP_BW_MODE_MAX); update_bus = 1; } diff --git a/drivers/video/fbdev/msm/mdss_mdp_trace.h b/drivers/video/fbdev/msm/mdss_mdp_trace.h index 08f7ec9ef975..3ecbd6c245c8 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_trace.h +++ b/drivers/video/fbdev/msm/mdss_mdp_trace.h @@ -205,22 +205,26 @@ TRACE_EVENT(mdp_video_underrun_done, TRACE_EVENT(mdp_perf_update_bus, TP_PROTO(unsigned long long ab_quota_rt, - unsigned long long ab_quota_nrt, unsigned long long ib_quota), - TP_ARGS(ab_quota_rt, ab_quota_nrt, ib_quota), + unsigned long long ab_quota_nrt, unsigned long long ib_quota, + unsigned long bw_vote_mode), + TP_ARGS(ab_quota_rt, ab_quota_nrt, ib_quota, bw_vote_mode), TP_STRUCT__entry( __field(u64, ab_quota_rt) __field(u64, ab_quota_nrt) __field(u64, ib_quota) + __field(u32, bw_vote_mode) ), TP_fast_assign( __entry->ab_quota_rt = ab_quota_rt; __entry->ab_quota_nrt = ab_quota_nrt; __entry->ib_quota = ib_quota; + __entry->bw_vote_mode = bw_vote_mode; ), - TP_printk("ab_rt=%llu ab_nrt=%llu ib=%llu", + TP_printk("ab_rt=%llu ab_nrt=%llu ib=%llu mode=%d", __entry->ab_quota_rt, __entry->ab_quota_nrt, - __entry->ib_quota) + __entry->ib_quota, + __entry->bw_vote_mode) ); TRACE_EVENT(mdp_cmd_pingpong_done,