Loading Documentation/devicetree/bindings/fb/mdss-mdp.txt +5 −0 Original line number Diff line number Diff line Loading @@ -320,6 +320,10 @@ Optional properties: priority for real time clients. - qcom,mdss-vbif-qos-nrt-setting: This array is used to program vbif qos remapper register priority for non real time clients. - qcom,mdss-traffic-shaper-enabled: This boolean property enables traffic shaper functionality for MDSS rotator which spread out rotator bandwidth request so that rotator don't compete with other real time read clients. Fudge Factors: Fudge factors are used to boost demand for resources like bus bandswidth, clk rate etc. to Loading Loading @@ -484,6 +488,7 @@ Example: qcom,mdss-has-source-split; qcom,mdss-wfd-mode = "intf"; qcom,mdss-no-lut-read; qcom,mdss-traffic-shaper-enabled; qcom,mdss-pipe-vig-xin-id = <0 4 8>; qcom,mdss-pipe-rgb-xin-id = <1 5 9>; Loading drivers/video/msm/mdss/mdss.h +2 −0 Original line number Diff line number Diff line Loading @@ -214,6 +214,8 @@ struct mdss_data_type { int handoff_pending; bool idle_pc; struct mdss_perf_tune perf_tune; bool traffic_shaper_en; }; extern struct mdss_data_type *mdss_res; Loading drivers/video/msm/mdss/mdss_mdp.c +2 −7 Original line number Diff line number Diff line Loading @@ -591,13 +591,6 @@ void mdss_mdp_irq_disable_nosync(u32 intr_type, u32 intf_num) } } static inline struct clk *mdss_mdp_get_clk(u32 clk_idx) { if (clk_idx < MDSS_MAX_CLK) return mdss_res->mdp_clk[clk_idx]; return NULL; } static int mdss_mdp_clk_update(u32 clk_idx, u32 enable) { int ret = -ENODEV; Loading Loading @@ -2543,6 +2536,8 @@ static int mdss_mdp_parse_dt_misc(struct platform_device *pdev) } mdss_mdp_parse_vbif_qos(pdev); mdata->traffic_shaper_en = of_property_read_bool(pdev->dev.of_node, "qcom,mdss-traffic-shaper-enabled"); return 0; } Loading drivers/video/msm/mdss/mdss_mdp.h +11 −0 Original line number Diff line number Diff line Loading @@ -170,6 +170,9 @@ struct mdss_mdp_ctl { u32 perf_transaction_status; bool perf_release_ctl_bw; bool traffic_shaper_enabled; u32 traffic_shaper_mdp_clk; struct mdss_data_type *mdata; struct msm_fb_data_type *mfd; struct mdss_mdp_mixer *mixer_left; Loading Loading @@ -557,6 +560,13 @@ static inline int mdss_mdp_panic_signal_supported( pipe->mixer_left->type == MDSS_MDP_MIXER_TYPE_INTF); } static inline struct clk *mdss_mdp_get_clk(u32 clk_idx) { if (clk_idx < MDSS_MAX_CLK) return mdss_res->mdp_clk[clk_idx]; return NULL; } irqreturn_t mdss_mdp_isr(int irq, void *ptr); int mdss_iommu_attach(struct mdss_data_type *mdata); int mdss_iommu_dettach(struct mdss_data_type *mdata); Loading Loading @@ -628,6 +638,7 @@ int mdss_mdp_perf_bw_check_pipe(struct mdss_mdp_perf_params *perf, int mdss_mdp_perf_calc_pipe(struct mdss_mdp_pipe *pipe, struct mdss_mdp_perf_params *perf, struct mdss_rect *roi, bool apply_fudge); u32 mdss_mdp_get_mdp_clk_rate(struct mdss_data_type *mdata); int mdss_mdp_ctl_notify(struct mdss_mdp_ctl *ctl, int event); void mdss_mdp_ctl_notifier_register(struct mdss_mdp_ctl *ctl, struct notifier_block *notifier); Loading drivers/video/msm/mdss/mdss_mdp_ctl.c +98 −33 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <linux/dma-mapping.h> #include <linux/delay.h> #include <linux/sort.h> #include <linux/clk.h> #include "mdss_fb.h" #include "mdss_mdp.h" Loading Loading @@ -386,6 +387,7 @@ int mdss_mdp_perf_calc_pipe(struct mdss_mdp_pipe *pipe, src = pipe->src; if (mixer->rotator_mode) { fps = DEFAULT_ROTATOR_FRAME_RATE; v_total = pipe->flags & MDP_ROT_90 ? pipe->dst.w : pipe->dst.h; } else if (mixer->type == MDSS_MDP_MIXER_TYPE_INTF) { struct mdss_panel_info *pinfo; Loading Loading @@ -946,23 +948,52 @@ u32 mdss_mdp_ctl_perf_get_transaction_status(struct mdss_mdp_ctl *ctl) return transaction_status; } static inline void mdss_mdp_ctl_perf_update_bus(struct mdss_mdp_ctl *ctl) /** * @ mdss_mdp_ctl_perf_update_traffic_shaper_bw - * Apply BW fudge factor to rotator * if mdp clock increased during * rotation session. * @ctl - pointer to the controller * @mdp_clk - new mdp clock * * If mdp clock increased and traffic shaper is enabled, we need to * account for the additional bandwidth that will be requested by * the rotator when running at a higher clock, so we apply a fudge * factor proportional to the mdp clock increment. */ static void mdss_mdp_ctl_perf_update_traffic_shaper_bw(struct mdss_mdp_ctl *ctl, u32 mdp_clk) { if ((mdp_clk > 0) && (mdp_clk > ctl->traffic_shaper_mdp_clk)) { ctl->cur_perf.bw_ctl = fudge_factor(ctl->cur_perf.bw_ctl, mdp_clk, ctl->traffic_shaper_mdp_clk); pr_debug("traffic shaper bw:%llu, clk: %d, mdp_clk:%d\n", ctl->cur_perf.bw_ctl, ctl->traffic_shaper_mdp_clk, mdp_clk); } } static inline void mdss_mdp_ctl_perf_update_bus(struct mdss_data_type *mdata, u32 mdp_clk) { u64 bw_sum_of_intfs = 0; u64 bus_ab_quota, bus_ib_quota; struct mdss_data_type *mdata; int i; if (!ctl || !ctl->mdata) return; ATRACE_BEGIN(__func__); mdata = ctl->mdata; for (i = 0; i < mdata->nctl; i++) { struct mdss_mdp_ctl *ctl; ctl = mdata->ctl_off + i; if (ctl->power_on) { /* * If traffic shaper is enabled we must check * if additional bandwidth is required. */ if (ctl->traffic_shaper_enabled) mdss_mdp_ctl_perf_update_traffic_shaper_bw (ctl, mdp_clk); bw_sum_of_intfs += ctl->cur_perf.bw_ctl; pr_debug("c=%d bw=%llu\n", ctl->num, pr_debug("ctl_num=%d bw=%llu\n", ctl->num, ctl->cur_perf.bw_ctl); } } Loading Loading @@ -1017,23 +1048,16 @@ void mdss_mdp_ctl_perf_release_bw(struct mdss_mdp_ctl *ctl) ctl->cur_perf.bw_ctl = 0; ctl->new_perf.bw_ctl = 0; pr_debug("Release BW ctl=%d\n", ctl->num); mdss_mdp_ctl_perf_update_bus(ctl); mdss_mdp_ctl_perf_update_bus(mdata, 0); } exit: mutex_unlock(&mdss_mdp_ctl_lock); } static int mdss_mdp_select_clk_lvl(struct mdss_mdp_ctl *ctl, static int mdss_mdp_select_clk_lvl(struct mdss_data_type *mdata, u32 clk_rate) { int i; struct mdss_data_type *mdata; if (!ctl) return -ENODEV; mdata = ctl->mdata; for (i = 0; i < mdata->nclk_lvl; i++) { if (clk_rate > mdata->clock_levels[i]) { continue; Loading @@ -1054,6 +1078,40 @@ static void mdss_mdp_perf_release_ctl_bw(struct mdss_mdp_ctl *ctl, ctl->perf_release_ctl_bw = false; } u32 mdss_mdp_get_mdp_clk_rate(struct mdss_data_type *mdata) { u32 clk_rate = 0; uint i; struct clk *clk = mdss_mdp_get_clk(MDSS_CLK_MDP_SRC); for (i = 0; i < mdata->nctl; i++) { struct mdss_mdp_ctl *ctl; ctl = mdata->ctl_off + i; if (ctl->power_on) { clk_rate = max(ctl->cur_perf.mdp_clk_rate, clk_rate); clk_rate = clk_round_rate(clk, clk_rate); } } clk_rate = mdss_mdp_select_clk_lvl(mdata, clk_rate); pr_debug("clk:%u nctl:%d\n", clk_rate, mdata->nctl); return clk_rate; } static bool is_traffic_shaper_enabled(struct mdss_data_type *mdata) { uint i; for (i = 0; i < mdata->nctl; i++) { struct mdss_mdp_ctl *ctl; ctl = mdata->ctl_off + i; if (ctl->power_on) if (ctl->traffic_shaper_enabled) return true; } return false; } static void mdss_mdp_ctl_perf_update(struct mdss_mdp_ctl *ctl, int params_changed) { Loading @@ -1061,6 +1119,7 @@ static void mdss_mdp_ctl_perf_update(struct mdss_mdp_ctl *ctl, int update_bus = 0, update_clk = 0; struct mdss_data_type *mdata; bool is_bw_released; u32 clk_rate = 0; if (!ctl || !ctl->mdata) return; Loading @@ -1073,7 +1132,7 @@ static void mdss_mdp_ctl_perf_update(struct mdss_mdp_ctl *ctl, /* * We could have released the bandwidth if there were no transactions * pending, so we want to re-calculate the bandwidth in this situation * pending, so we want to re-calculate the bandwidth in this situation. */ is_bw_released = !mdss_mdp_ctl_perf_get_transaction_status(ctl); Loading @@ -1083,9 +1142,9 @@ static void mdss_mdp_ctl_perf_update(struct mdss_mdp_ctl *ctl, else if (is_bw_released || params_changed) mdss_mdp_perf_calc_ctl(ctl, new); /* * if params have just changed delay the update until * If params have just changed delay the update until * later once the hw configuration has been flushed to * MDP * MDP. */ if ((params_changed && (new->bw_ctl > old->bw_ctl)) || (!params_changed && (new->bw_ctl < old->bw_ctl))) { Loading @@ -1096,9 +1155,15 @@ static void mdss_mdp_ctl_perf_update(struct mdss_mdp_ctl *ctl, update_bus = 1; } /* * If traffic shaper is enabled, we do not decrease the clock, * otherwise we would increase traffic shaper latency. Clock * would be decreased after traffic shaper is done. */ if ((params_changed && (new->mdp_clk_rate > old->mdp_clk_rate)) || (!params_changed && (new->mdp_clk_rate < old->mdp_clk_rate))) { || (!params_changed && (new->mdp_clk_rate < old->mdp_clk_rate) && (false == is_traffic_shaper_enabled(mdata)))) { old->mdp_clk_rate = new->mdp_clk_rate; update_clk = 1; } Loading @@ -1109,22 +1174,22 @@ static void mdss_mdp_ctl_perf_update(struct mdss_mdp_ctl *ctl, update_clk = 1; } /* * Calculate mdp clock before bandwidth calculation. If traffic shaper * is enabled and clock increased, the bandwidth calculation can * use the new clock for the rotator bw calculation. */ if (update_clk) clk_rate = mdss_mdp_get_mdp_clk_rate(mdata); if (update_bus) mdss_mdp_ctl_perf_update_bus(ctl); mdss_mdp_ctl_perf_update_bus(mdata, clk_rate); /* * Update the clock after bandwidth vote to ensure * bandwidth is available before clock rate is increased. */ if (update_clk) { u32 clk_rate = 0; int i; for (i = 0; i < mdata->nctl; i++) { struct mdss_mdp_ctl *ctl; ctl = mdata->ctl_off + i; if (ctl->power_on) clk_rate = max(ctl->cur_perf.mdp_clk_rate, clk_rate); } clk_rate = mdss_mdp_select_clk_lvl(ctl, clk_rate); ATRACE_INT("mdp_clk", clk_rate); mdss_mdp_set_clk_rate(clk_rate); pr_debug("update clk rate = %d HZ\n", clk_rate); Loading Loading
Documentation/devicetree/bindings/fb/mdss-mdp.txt +5 −0 Original line number Diff line number Diff line Loading @@ -320,6 +320,10 @@ Optional properties: priority for real time clients. - qcom,mdss-vbif-qos-nrt-setting: This array is used to program vbif qos remapper register priority for non real time clients. - qcom,mdss-traffic-shaper-enabled: This boolean property enables traffic shaper functionality for MDSS rotator which spread out rotator bandwidth request so that rotator don't compete with other real time read clients. Fudge Factors: Fudge factors are used to boost demand for resources like bus bandswidth, clk rate etc. to Loading Loading @@ -484,6 +488,7 @@ Example: qcom,mdss-has-source-split; qcom,mdss-wfd-mode = "intf"; qcom,mdss-no-lut-read; qcom,mdss-traffic-shaper-enabled; qcom,mdss-pipe-vig-xin-id = <0 4 8>; qcom,mdss-pipe-rgb-xin-id = <1 5 9>; Loading
drivers/video/msm/mdss/mdss.h +2 −0 Original line number Diff line number Diff line Loading @@ -214,6 +214,8 @@ struct mdss_data_type { int handoff_pending; bool idle_pc; struct mdss_perf_tune perf_tune; bool traffic_shaper_en; }; extern struct mdss_data_type *mdss_res; Loading
drivers/video/msm/mdss/mdss_mdp.c +2 −7 Original line number Diff line number Diff line Loading @@ -591,13 +591,6 @@ void mdss_mdp_irq_disable_nosync(u32 intr_type, u32 intf_num) } } static inline struct clk *mdss_mdp_get_clk(u32 clk_idx) { if (clk_idx < MDSS_MAX_CLK) return mdss_res->mdp_clk[clk_idx]; return NULL; } static int mdss_mdp_clk_update(u32 clk_idx, u32 enable) { int ret = -ENODEV; Loading Loading @@ -2543,6 +2536,8 @@ static int mdss_mdp_parse_dt_misc(struct platform_device *pdev) } mdss_mdp_parse_vbif_qos(pdev); mdata->traffic_shaper_en = of_property_read_bool(pdev->dev.of_node, "qcom,mdss-traffic-shaper-enabled"); return 0; } Loading
drivers/video/msm/mdss/mdss_mdp.h +11 −0 Original line number Diff line number Diff line Loading @@ -170,6 +170,9 @@ struct mdss_mdp_ctl { u32 perf_transaction_status; bool perf_release_ctl_bw; bool traffic_shaper_enabled; u32 traffic_shaper_mdp_clk; struct mdss_data_type *mdata; struct msm_fb_data_type *mfd; struct mdss_mdp_mixer *mixer_left; Loading Loading @@ -557,6 +560,13 @@ static inline int mdss_mdp_panic_signal_supported( pipe->mixer_left->type == MDSS_MDP_MIXER_TYPE_INTF); } static inline struct clk *mdss_mdp_get_clk(u32 clk_idx) { if (clk_idx < MDSS_MAX_CLK) return mdss_res->mdp_clk[clk_idx]; return NULL; } irqreturn_t mdss_mdp_isr(int irq, void *ptr); int mdss_iommu_attach(struct mdss_data_type *mdata); int mdss_iommu_dettach(struct mdss_data_type *mdata); Loading Loading @@ -628,6 +638,7 @@ int mdss_mdp_perf_bw_check_pipe(struct mdss_mdp_perf_params *perf, int mdss_mdp_perf_calc_pipe(struct mdss_mdp_pipe *pipe, struct mdss_mdp_perf_params *perf, struct mdss_rect *roi, bool apply_fudge); u32 mdss_mdp_get_mdp_clk_rate(struct mdss_data_type *mdata); int mdss_mdp_ctl_notify(struct mdss_mdp_ctl *ctl, int event); void mdss_mdp_ctl_notifier_register(struct mdss_mdp_ctl *ctl, struct notifier_block *notifier); Loading
drivers/video/msm/mdss/mdss_mdp_ctl.c +98 −33 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <linux/dma-mapping.h> #include <linux/delay.h> #include <linux/sort.h> #include <linux/clk.h> #include "mdss_fb.h" #include "mdss_mdp.h" Loading Loading @@ -386,6 +387,7 @@ int mdss_mdp_perf_calc_pipe(struct mdss_mdp_pipe *pipe, src = pipe->src; if (mixer->rotator_mode) { fps = DEFAULT_ROTATOR_FRAME_RATE; v_total = pipe->flags & MDP_ROT_90 ? pipe->dst.w : pipe->dst.h; } else if (mixer->type == MDSS_MDP_MIXER_TYPE_INTF) { struct mdss_panel_info *pinfo; Loading Loading @@ -946,23 +948,52 @@ u32 mdss_mdp_ctl_perf_get_transaction_status(struct mdss_mdp_ctl *ctl) return transaction_status; } static inline void mdss_mdp_ctl_perf_update_bus(struct mdss_mdp_ctl *ctl) /** * @ mdss_mdp_ctl_perf_update_traffic_shaper_bw - * Apply BW fudge factor to rotator * if mdp clock increased during * rotation session. * @ctl - pointer to the controller * @mdp_clk - new mdp clock * * If mdp clock increased and traffic shaper is enabled, we need to * account for the additional bandwidth that will be requested by * the rotator when running at a higher clock, so we apply a fudge * factor proportional to the mdp clock increment. */ static void mdss_mdp_ctl_perf_update_traffic_shaper_bw(struct mdss_mdp_ctl *ctl, u32 mdp_clk) { if ((mdp_clk > 0) && (mdp_clk > ctl->traffic_shaper_mdp_clk)) { ctl->cur_perf.bw_ctl = fudge_factor(ctl->cur_perf.bw_ctl, mdp_clk, ctl->traffic_shaper_mdp_clk); pr_debug("traffic shaper bw:%llu, clk: %d, mdp_clk:%d\n", ctl->cur_perf.bw_ctl, ctl->traffic_shaper_mdp_clk, mdp_clk); } } static inline void mdss_mdp_ctl_perf_update_bus(struct mdss_data_type *mdata, u32 mdp_clk) { u64 bw_sum_of_intfs = 0; u64 bus_ab_quota, bus_ib_quota; struct mdss_data_type *mdata; int i; if (!ctl || !ctl->mdata) return; ATRACE_BEGIN(__func__); mdata = ctl->mdata; for (i = 0; i < mdata->nctl; i++) { struct mdss_mdp_ctl *ctl; ctl = mdata->ctl_off + i; if (ctl->power_on) { /* * If traffic shaper is enabled we must check * if additional bandwidth is required. */ if (ctl->traffic_shaper_enabled) mdss_mdp_ctl_perf_update_traffic_shaper_bw (ctl, mdp_clk); bw_sum_of_intfs += ctl->cur_perf.bw_ctl; pr_debug("c=%d bw=%llu\n", ctl->num, pr_debug("ctl_num=%d bw=%llu\n", ctl->num, ctl->cur_perf.bw_ctl); } } Loading Loading @@ -1017,23 +1048,16 @@ void mdss_mdp_ctl_perf_release_bw(struct mdss_mdp_ctl *ctl) ctl->cur_perf.bw_ctl = 0; ctl->new_perf.bw_ctl = 0; pr_debug("Release BW ctl=%d\n", ctl->num); mdss_mdp_ctl_perf_update_bus(ctl); mdss_mdp_ctl_perf_update_bus(mdata, 0); } exit: mutex_unlock(&mdss_mdp_ctl_lock); } static int mdss_mdp_select_clk_lvl(struct mdss_mdp_ctl *ctl, static int mdss_mdp_select_clk_lvl(struct mdss_data_type *mdata, u32 clk_rate) { int i; struct mdss_data_type *mdata; if (!ctl) return -ENODEV; mdata = ctl->mdata; for (i = 0; i < mdata->nclk_lvl; i++) { if (clk_rate > mdata->clock_levels[i]) { continue; Loading @@ -1054,6 +1078,40 @@ static void mdss_mdp_perf_release_ctl_bw(struct mdss_mdp_ctl *ctl, ctl->perf_release_ctl_bw = false; } u32 mdss_mdp_get_mdp_clk_rate(struct mdss_data_type *mdata) { u32 clk_rate = 0; uint i; struct clk *clk = mdss_mdp_get_clk(MDSS_CLK_MDP_SRC); for (i = 0; i < mdata->nctl; i++) { struct mdss_mdp_ctl *ctl; ctl = mdata->ctl_off + i; if (ctl->power_on) { clk_rate = max(ctl->cur_perf.mdp_clk_rate, clk_rate); clk_rate = clk_round_rate(clk, clk_rate); } } clk_rate = mdss_mdp_select_clk_lvl(mdata, clk_rate); pr_debug("clk:%u nctl:%d\n", clk_rate, mdata->nctl); return clk_rate; } static bool is_traffic_shaper_enabled(struct mdss_data_type *mdata) { uint i; for (i = 0; i < mdata->nctl; i++) { struct mdss_mdp_ctl *ctl; ctl = mdata->ctl_off + i; if (ctl->power_on) if (ctl->traffic_shaper_enabled) return true; } return false; } static void mdss_mdp_ctl_perf_update(struct mdss_mdp_ctl *ctl, int params_changed) { Loading @@ -1061,6 +1119,7 @@ static void mdss_mdp_ctl_perf_update(struct mdss_mdp_ctl *ctl, int update_bus = 0, update_clk = 0; struct mdss_data_type *mdata; bool is_bw_released; u32 clk_rate = 0; if (!ctl || !ctl->mdata) return; Loading @@ -1073,7 +1132,7 @@ static void mdss_mdp_ctl_perf_update(struct mdss_mdp_ctl *ctl, /* * We could have released the bandwidth if there were no transactions * pending, so we want to re-calculate the bandwidth in this situation * pending, so we want to re-calculate the bandwidth in this situation. */ is_bw_released = !mdss_mdp_ctl_perf_get_transaction_status(ctl); Loading @@ -1083,9 +1142,9 @@ static void mdss_mdp_ctl_perf_update(struct mdss_mdp_ctl *ctl, else if (is_bw_released || params_changed) mdss_mdp_perf_calc_ctl(ctl, new); /* * if params have just changed delay the update until * If params have just changed delay the update until * later once the hw configuration has been flushed to * MDP * MDP. */ if ((params_changed && (new->bw_ctl > old->bw_ctl)) || (!params_changed && (new->bw_ctl < old->bw_ctl))) { Loading @@ -1096,9 +1155,15 @@ static void mdss_mdp_ctl_perf_update(struct mdss_mdp_ctl *ctl, update_bus = 1; } /* * If traffic shaper is enabled, we do not decrease the clock, * otherwise we would increase traffic shaper latency. Clock * would be decreased after traffic shaper is done. */ if ((params_changed && (new->mdp_clk_rate > old->mdp_clk_rate)) || (!params_changed && (new->mdp_clk_rate < old->mdp_clk_rate))) { || (!params_changed && (new->mdp_clk_rate < old->mdp_clk_rate) && (false == is_traffic_shaper_enabled(mdata)))) { old->mdp_clk_rate = new->mdp_clk_rate; update_clk = 1; } Loading @@ -1109,22 +1174,22 @@ static void mdss_mdp_ctl_perf_update(struct mdss_mdp_ctl *ctl, update_clk = 1; } /* * Calculate mdp clock before bandwidth calculation. If traffic shaper * is enabled and clock increased, the bandwidth calculation can * use the new clock for the rotator bw calculation. */ if (update_clk) clk_rate = mdss_mdp_get_mdp_clk_rate(mdata); if (update_bus) mdss_mdp_ctl_perf_update_bus(ctl); mdss_mdp_ctl_perf_update_bus(mdata, clk_rate); /* * Update the clock after bandwidth vote to ensure * bandwidth is available before clock rate is increased. */ if (update_clk) { u32 clk_rate = 0; int i; for (i = 0; i < mdata->nctl; i++) { struct mdss_mdp_ctl *ctl; ctl = mdata->ctl_off + i; if (ctl->power_on) clk_rate = max(ctl->cur_perf.mdp_clk_rate, clk_rate); } clk_rate = mdss_mdp_select_clk_lvl(ctl, clk_rate); ATRACE_INT("mdp_clk", clk_rate); mdss_mdp_set_clk_rate(clk_rate); pr_debug("update clk rate = %d HZ\n", clk_rate); Loading