Loading drivers/video/msm/mdss/mdss_mdp.h +3 −0 Original line number Diff line number Diff line Loading @@ -574,6 +574,9 @@ int mdss_mdp_ctl_destroy(struct mdss_mdp_ctl *ctl); int mdss_mdp_ctl_start(struct mdss_mdp_ctl *ctl, bool handoff); int mdss_mdp_ctl_stop(struct mdss_mdp_ctl *ctl); int mdss_mdp_ctl_intf_event(struct mdss_mdp_ctl *ctl, int event, void *arg); int mdss_mdp_perf_bw_check(struct mdss_mdp_ctl *ctl, struct mdss_mdp_pipe **left_plist, int left_cnt, struct mdss_mdp_pipe **right_plist, int right_cnt); int mdss_mdp_perf_calc_pipe(struct mdss_mdp_pipe *pipe, struct mdss_mdp_perf_params *perf, struct mdss_mdp_img_rect *roi, bool apply_fudge); Loading drivers/video/msm/mdss/mdss_mdp_ctl.c +65 −17 Original line number Diff line number Diff line Loading @@ -426,7 +426,8 @@ static inline int cmpu32(const void *a, const void *b) } static void mdss_mdp_perf_calc_mixer(struct mdss_mdp_mixer *mixer, struct mdss_mdp_perf_params *perf) struct mdss_mdp_perf_params *perf, struct mdss_mdp_pipe **pipe_list, int num_pipes) { struct mdss_mdp_pipe *pipe; struct mdss_panel_info *pinfo = NULL; Loading @@ -435,12 +436,14 @@ static void mdss_mdp_perf_calc_mixer(struct mdss_mdp_mixer *mixer, int i; u32 max_clk_rate = 0; u64 bw_overlap_max = 0; u64 bw_overlap[MDSS_MDP_MAX_STAGE]; u32 v_region[MDSS_MDP_MAX_STAGE * 2]; u64 bw_overlap[MDSS_MDP_MAX_STAGE] = { 0 }; u32 v_region[MDSS_MDP_MAX_STAGE * 2] = { 0 }; u32 prefill_bytes = 0; struct mdss_data_type *mdata = mdss_mdp_get_mdata(); bool apply_fudge = true; BUG_ON(num_pipes > MDSS_MDP_MAX_STAGE); memset(perf, 0, sizeof(*perf)); if (!mixer->rotator_mode) { Loading Loading @@ -474,8 +477,8 @@ static void mdss_mdp_perf_calc_mixer(struct mdss_mdp_mixer *mixer, if (IS_MDSS_MAJOR_MINOR_SAME(mdata->mdp_rev, MDSS_MDP_HW_REV_101) && mixer->type == MDSS_MDP_MIXER_TYPE_INTF) { u32 npipes = 0; for (i = 0; i < MDSS_MDP_MAX_STAGE; i++) { pipe = mixer->stage_pipe[i]; for (i = 0; i < num_pipes; i++) { pipe = pipe_list[i]; if (pipe) { if (npipes) { apply_fudge = true; Loading @@ -489,9 +492,9 @@ static void mdss_mdp_perf_calc_mixer(struct mdss_mdp_mixer *mixer, } } for (i = 0; i < MDSS_MDP_MAX_STAGE; i++) { for (i = 0; i < num_pipes; i++) { struct mdss_mdp_perf_params tmp; pipe = mixer->stage_pipe[i]; pipe = pipe_list[i]; if (pipe == NULL) continue; Loading @@ -512,8 +515,8 @@ static void mdss_mdp_perf_calc_mixer(struct mdss_mdp_mixer *mixer, * data for each region and sum them up, then the worst case * of all regions is ib request. */ sort(v_region, MDSS_MDP_MAX_STAGE * 2, sizeof(u32), cmpu32, NULL); for (i = 1; i < MDSS_MDP_MAX_STAGE * 2; i++) { sort(v_region, num_pipes * 2, sizeof(u32), cmpu32, NULL); for (i = 1; i < num_pipes * 2; i++) { int j; u64 bw_max_region = 0; u32 y0, y1; Loading @@ -522,10 +525,10 @@ static void mdss_mdp_perf_calc_mixer(struct mdss_mdp_mixer *mixer, continue; y0 = (v_region[i-1]) ? v_region[i-1] + 1 : 0; y1 = v_region[i]; for (j = 0; j < MDSS_MDP_MAX_STAGE; j++) { for (j = 0; j < num_pipes; j++) { if (!bw_overlap[j]) continue; pipe = mixer->stage_pipe[j]; pipe = pipe_list[j]; if (mdss_mdp_perf_is_overlap(y0, y1, pipe->dst.y, (pipe->dst.y + pipe->dst.h))) bw_max_region += bw_overlap[j]; Loading Loading @@ -590,22 +593,26 @@ static u32 mdss_mdp_get_vbp_factor_max(struct mdss_mdp_ctl *ctl) return vbp_max; } static void mdss_mdp_perf_calc_ctl(struct mdss_mdp_ctl *ctl, struct mdss_mdp_perf_params *perf) static void __mdss_mdp_perf_calc_ctl_helper(struct mdss_mdp_ctl *ctl, struct mdss_mdp_perf_params *perf, struct mdss_mdp_pipe **left_plist, int left_cnt, struct mdss_mdp_pipe **right_plist, int right_cnt) { struct mdss_mdp_perf_params tmp; memset(perf, 0, sizeof(*perf)); if (ctl->mixer_left) { mdss_mdp_perf_calc_mixer(ctl->mixer_left, &tmp); if (left_cnt && ctl->mixer_left) { mdss_mdp_perf_calc_mixer(ctl->mixer_left, &tmp, left_plist, left_cnt); perf->bw_overlap += tmp.bw_overlap; perf->prefill_bytes += tmp.prefill_bytes; perf->mdp_clk_rate = tmp.mdp_clk_rate; } if (ctl->mixer_right) { mdss_mdp_perf_calc_mixer(ctl->mixer_right, &tmp); if (right_cnt && ctl->mixer_right) { mdss_mdp_perf_calc_mixer(ctl->mixer_right, &tmp, right_plist, right_cnt); perf->bw_overlap += tmp.bw_overlap; perf->prefill_bytes += tmp.prefill_bytes; if (tmp.mdp_clk_rate > perf->mdp_clk_rate) Loading Loading @@ -642,6 +649,47 @@ static void mdss_mdp_perf_calc_ctl(struct mdss_mdp_ctl *ctl, if (ctl->is_video_mode) perf->bw_ctl = IB_FUDGE_FACTOR(perf->bw_ctl); } int mdss_mdp_perf_bw_check(struct mdss_mdp_ctl *ctl, struct mdss_mdp_pipe **left_plist, int left_cnt, struct mdss_mdp_pipe **right_plist, int right_cnt) { struct mdss_data_type *mdata = ctl->mdata; struct mdss_mdp_perf_params perf; u32 bw, threshold; /* we only need bandwidth check on real-time clients (interfaces) */ if (ctl->intf_type == MDSS_MDP_NO_INTF) return 0; __mdss_mdp_perf_calc_ctl_helper(ctl, &perf, left_plist, left_cnt, right_plist, right_cnt); /* convert bandwidth to kb */ bw = DIV_ROUND_UP_ULL(perf.bw_ctl, 1000); pr_debug("calculated bandwidth=%uk\n", bw); threshold = ctl->is_video_mode ? mdata->max_bw_low : mdata->max_bw_high; if (bw > threshold) { pr_debug("exceeds bandwidth: %ukb > %ukb\n", bw, threshold); return -E2BIG; } return 0; } static void mdss_mdp_perf_calc_ctl(struct mdss_mdp_ctl *ctl, struct mdss_mdp_perf_params *perf) { struct mdss_mdp_pipe **left_plist, **right_plist; left_plist = ctl->mixer_left ? ctl->mixer_left->stage_pipe : NULL; right_plist = ctl->mixer_right ? ctl->mixer_right->stage_pipe : NULL; __mdss_mdp_perf_calc_ctl_helper(ctl, perf, left_plist, (left_plist ? MDSS_MDP_MAX_STAGE : 0), right_plist, (right_plist ? MDSS_MDP_MAX_STAGE : 0)); pr_debug("ctl=%d clk_rate=%u\n", ctl->num, perf->mdp_clk_rate); pr_debug("bw_overlap=%llu bw_prefill=%llu prefill_byptes=%d\n", Loading Loading
drivers/video/msm/mdss/mdss_mdp.h +3 −0 Original line number Diff line number Diff line Loading @@ -574,6 +574,9 @@ int mdss_mdp_ctl_destroy(struct mdss_mdp_ctl *ctl); int mdss_mdp_ctl_start(struct mdss_mdp_ctl *ctl, bool handoff); int mdss_mdp_ctl_stop(struct mdss_mdp_ctl *ctl); int mdss_mdp_ctl_intf_event(struct mdss_mdp_ctl *ctl, int event, void *arg); int mdss_mdp_perf_bw_check(struct mdss_mdp_ctl *ctl, struct mdss_mdp_pipe **left_plist, int left_cnt, struct mdss_mdp_pipe **right_plist, int right_cnt); int mdss_mdp_perf_calc_pipe(struct mdss_mdp_pipe *pipe, struct mdss_mdp_perf_params *perf, struct mdss_mdp_img_rect *roi, bool apply_fudge); Loading
drivers/video/msm/mdss/mdss_mdp_ctl.c +65 −17 Original line number Diff line number Diff line Loading @@ -426,7 +426,8 @@ static inline int cmpu32(const void *a, const void *b) } static void mdss_mdp_perf_calc_mixer(struct mdss_mdp_mixer *mixer, struct mdss_mdp_perf_params *perf) struct mdss_mdp_perf_params *perf, struct mdss_mdp_pipe **pipe_list, int num_pipes) { struct mdss_mdp_pipe *pipe; struct mdss_panel_info *pinfo = NULL; Loading @@ -435,12 +436,14 @@ static void mdss_mdp_perf_calc_mixer(struct mdss_mdp_mixer *mixer, int i; u32 max_clk_rate = 0; u64 bw_overlap_max = 0; u64 bw_overlap[MDSS_MDP_MAX_STAGE]; u32 v_region[MDSS_MDP_MAX_STAGE * 2]; u64 bw_overlap[MDSS_MDP_MAX_STAGE] = { 0 }; u32 v_region[MDSS_MDP_MAX_STAGE * 2] = { 0 }; u32 prefill_bytes = 0; struct mdss_data_type *mdata = mdss_mdp_get_mdata(); bool apply_fudge = true; BUG_ON(num_pipes > MDSS_MDP_MAX_STAGE); memset(perf, 0, sizeof(*perf)); if (!mixer->rotator_mode) { Loading Loading @@ -474,8 +477,8 @@ static void mdss_mdp_perf_calc_mixer(struct mdss_mdp_mixer *mixer, if (IS_MDSS_MAJOR_MINOR_SAME(mdata->mdp_rev, MDSS_MDP_HW_REV_101) && mixer->type == MDSS_MDP_MIXER_TYPE_INTF) { u32 npipes = 0; for (i = 0; i < MDSS_MDP_MAX_STAGE; i++) { pipe = mixer->stage_pipe[i]; for (i = 0; i < num_pipes; i++) { pipe = pipe_list[i]; if (pipe) { if (npipes) { apply_fudge = true; Loading @@ -489,9 +492,9 @@ static void mdss_mdp_perf_calc_mixer(struct mdss_mdp_mixer *mixer, } } for (i = 0; i < MDSS_MDP_MAX_STAGE; i++) { for (i = 0; i < num_pipes; i++) { struct mdss_mdp_perf_params tmp; pipe = mixer->stage_pipe[i]; pipe = pipe_list[i]; if (pipe == NULL) continue; Loading @@ -512,8 +515,8 @@ static void mdss_mdp_perf_calc_mixer(struct mdss_mdp_mixer *mixer, * data for each region and sum them up, then the worst case * of all regions is ib request. */ sort(v_region, MDSS_MDP_MAX_STAGE * 2, sizeof(u32), cmpu32, NULL); for (i = 1; i < MDSS_MDP_MAX_STAGE * 2; i++) { sort(v_region, num_pipes * 2, sizeof(u32), cmpu32, NULL); for (i = 1; i < num_pipes * 2; i++) { int j; u64 bw_max_region = 0; u32 y0, y1; Loading @@ -522,10 +525,10 @@ static void mdss_mdp_perf_calc_mixer(struct mdss_mdp_mixer *mixer, continue; y0 = (v_region[i-1]) ? v_region[i-1] + 1 : 0; y1 = v_region[i]; for (j = 0; j < MDSS_MDP_MAX_STAGE; j++) { for (j = 0; j < num_pipes; j++) { if (!bw_overlap[j]) continue; pipe = mixer->stage_pipe[j]; pipe = pipe_list[j]; if (mdss_mdp_perf_is_overlap(y0, y1, pipe->dst.y, (pipe->dst.y + pipe->dst.h))) bw_max_region += bw_overlap[j]; Loading Loading @@ -590,22 +593,26 @@ static u32 mdss_mdp_get_vbp_factor_max(struct mdss_mdp_ctl *ctl) return vbp_max; } static void mdss_mdp_perf_calc_ctl(struct mdss_mdp_ctl *ctl, struct mdss_mdp_perf_params *perf) static void __mdss_mdp_perf_calc_ctl_helper(struct mdss_mdp_ctl *ctl, struct mdss_mdp_perf_params *perf, struct mdss_mdp_pipe **left_plist, int left_cnt, struct mdss_mdp_pipe **right_plist, int right_cnt) { struct mdss_mdp_perf_params tmp; memset(perf, 0, sizeof(*perf)); if (ctl->mixer_left) { mdss_mdp_perf_calc_mixer(ctl->mixer_left, &tmp); if (left_cnt && ctl->mixer_left) { mdss_mdp_perf_calc_mixer(ctl->mixer_left, &tmp, left_plist, left_cnt); perf->bw_overlap += tmp.bw_overlap; perf->prefill_bytes += tmp.prefill_bytes; perf->mdp_clk_rate = tmp.mdp_clk_rate; } if (ctl->mixer_right) { mdss_mdp_perf_calc_mixer(ctl->mixer_right, &tmp); if (right_cnt && ctl->mixer_right) { mdss_mdp_perf_calc_mixer(ctl->mixer_right, &tmp, right_plist, right_cnt); perf->bw_overlap += tmp.bw_overlap; perf->prefill_bytes += tmp.prefill_bytes; if (tmp.mdp_clk_rate > perf->mdp_clk_rate) Loading Loading @@ -642,6 +649,47 @@ static void mdss_mdp_perf_calc_ctl(struct mdss_mdp_ctl *ctl, if (ctl->is_video_mode) perf->bw_ctl = IB_FUDGE_FACTOR(perf->bw_ctl); } int mdss_mdp_perf_bw_check(struct mdss_mdp_ctl *ctl, struct mdss_mdp_pipe **left_plist, int left_cnt, struct mdss_mdp_pipe **right_plist, int right_cnt) { struct mdss_data_type *mdata = ctl->mdata; struct mdss_mdp_perf_params perf; u32 bw, threshold; /* we only need bandwidth check on real-time clients (interfaces) */ if (ctl->intf_type == MDSS_MDP_NO_INTF) return 0; __mdss_mdp_perf_calc_ctl_helper(ctl, &perf, left_plist, left_cnt, right_plist, right_cnt); /* convert bandwidth to kb */ bw = DIV_ROUND_UP_ULL(perf.bw_ctl, 1000); pr_debug("calculated bandwidth=%uk\n", bw); threshold = ctl->is_video_mode ? mdata->max_bw_low : mdata->max_bw_high; if (bw > threshold) { pr_debug("exceeds bandwidth: %ukb > %ukb\n", bw, threshold); return -E2BIG; } return 0; } static void mdss_mdp_perf_calc_ctl(struct mdss_mdp_ctl *ctl, struct mdss_mdp_perf_params *perf) { struct mdss_mdp_pipe **left_plist, **right_plist; left_plist = ctl->mixer_left ? ctl->mixer_left->stage_pipe : NULL; right_plist = ctl->mixer_right ? ctl->mixer_right->stage_pipe : NULL; __mdss_mdp_perf_calc_ctl_helper(ctl, perf, left_plist, (left_plist ? MDSS_MDP_MAX_STAGE : 0), right_plist, (right_plist ? MDSS_MDP_MAX_STAGE : 0)); pr_debug("ctl=%d clk_rate=%u\n", ctl->num, perf->mdp_clk_rate); pr_debug("bw_overlap=%llu bw_prefill=%llu prefill_byptes=%d\n", Loading