Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 17004b6d authored by Jayant Shekhar's avatar Jayant Shekhar
Browse files

msm: mdss: Add traffic shaper for rotator path



Rotator is a non real time client. Traffic shaper helps
spread out rotator bandwidth request so that this non
real-time client won't compete with other real time
read clients.

Change-Id: I07dbc0a6287e31d33084e27a8e1f3e9ea365d3ab
Signed-off-by: default avatarJayant Shekhar <jshekhar@codeaurora.org>
parent e0fdefea
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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
@@ -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>;
+2 −0
Original line number Diff line number Diff line
@@ -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;

+2 −7
Original line number Diff line number Diff line
@@ -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;
@@ -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;
}
+11 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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);
@@ -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);
+98 −33
Original line number Diff line number Diff line
@@ -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"
@@ -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;
@@ -938,23 +940,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);
		}
	}
@@ -1009,23 +1040,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;
@@ -1046,6 +1070,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)
{
@@ -1053,6 +1111,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;
@@ -1065,7 +1124,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);

@@ -1075,9 +1134,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))) {
@@ -1088,9 +1147,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;
		}
@@ -1101,22 +1166,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