static void mdss_mdp_perf_calc_mixer(struct mdss_mdp_mixer *mixer,
		struct mdss_mdp_perf_params *perf)
{
	struct mdss_mdp_pipe *pipe;
	struct mdss_panel_info *pinfo = NULL;
	int fps = DEFAULT_FRAME_RATE;
	u32 v_total;
	int i;
	u32 max_clk_rate = 0, ab_total = 0, ib_total = 0;

	memset(perf, 0, sizeof(*perf));

	if (!mixer->rotator_mode) {
		if (mixer->type == MDSS_MDP_MIXER_TYPE_INTF) {
			pinfo = &mixer->ctl->panel_data->panel_info;
			fps = mdss_panel_get_framerate(pinfo);
			v_total = mdss_panel_get_vtotal(pinfo);

			if (pinfo->type == WRITEBACK_PANEL)
				pinfo = NULL;
		} else {
			v_total = mixer->height;
		}
		perf->mdp_clk_rate = mixer->width * v_total * fps;
		perf->mdp_clk_rate =
			MDSS_MDP_CLK_FUDGE_FACTOR(perf->mdp_clk_rate);

		if (!pinfo) {
			/* perf for bus writeback */
			perf->ab_quota = fps * mixer->width * mixer->height * 3;
			perf->ib_quota = perf->ab_quota;
		}
	}

	for (i = 0; i < MDSS_MDP_MAX_STAGE; i++) {
		struct mdss_mdp_perf_params tmp;
		pipe = mixer->stage_pipe[i];
		if (pipe == NULL)
			continue;

		if (mdss_mdp_perf_calc_pipe(pipe, &tmp))
			continue;

		ab_total += tmp.ab_quota >> MDSS_MDP_BUS_FACTOR_SHIFT;
		ib_total += tmp.ib_quota >> MDSS_MDP_BUS_FACTOR_SHIFT;
		if (tmp.mdp_clk_rate > max_clk_rate)
			max_clk_rate = tmp.mdp_clk_rate;
	}

	perf->ab_quota += ab_total << MDSS_MDP_BUS_FACTOR_SHIFT;
	perf->ib_quota += ib_total << MDSS_MDP_BUS_FACTOR_SHIFT;
	if (max_clk_rate > perf->mdp_clk_rate)
		perf->mdp_clk_rate = max_clk_rate;
}
Exemplo n.º 2
0
static int mdss_mdp_ctl_perf_commit(u32 flags)
{
	struct mdss_mdp_ctl *ctl;
	int cnum;
	unsigned long clk_rate = 0;
	u64 bus_ab_quota = 0, bus_ib_quota = 0;

	if (!flags) {
		pr_err("nothing to update\n");
		return -EINVAL;
	}

	mutex_lock(&mdss_mdp_ctl_lock);
	for (cnum = 0; cnum < MDSS_MDP_MAX_CTL; cnum++) {
		ctl = &mdss_mdp_ctl_list[cnum];
		if (ctl->power_on) {
			bus_ab_quota += ctl->bus_ab_quota;
			bus_ib_quota += ctl->bus_ib_quota;

			if (ctl->clk_rate > clk_rate)
				clk_rate = ctl->clk_rate;
		}
	}
	if (flags & MDSS_MDP_PERF_UPDATE_BUS) {
		bus_ab_quota = bus_ab_quota << MDSS_MDP_BUS_FACTOR_SHIFT;
		bus_ib_quota = MDSS_MDP_BUS_FUDGE_FACTOR(bus_ib_quota);
		bus_ib_quota <<= MDSS_MDP_BUS_FACTOR_SHIFT;

		if ((bus_ib_quota == 0) && (clk_rate > 0)) {
			/* allocate min bw for panel cmds if mdp is active */
			bus_ib_quota = SZ_16M;
		}
		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);
		mdss_mdp_set_clk_rate(clk_rate);
	}
	mutex_unlock(&mdss_mdp_ctl_lock);

	return 0;
}
static int mdss_mdp_ctl_perf_commit(struct mdss_data_type *mdata, u32 flags)
{
	struct mdss_mdp_ctl *ctl;
	int cnum;
	unsigned long clk_rate = 0;
	u64 bus_ab_quota = 0, bus_ib_quota = 0;

	if (!flags) {
		pr_err("nothing to update\n");
		return -EINVAL;
	}

	mutex_lock(&mdss_mdp_ctl_lock);
	for (cnum = 0; cnum < mdata->nctl; cnum++) {
		ctl = mdata->ctl_off + cnum;
		if (ctl->power_on) {
			struct mdss_mdp_perf_params *perf = &ctl->cur_perf;

			bus_ab_quota += perf->ab_quota;
			bus_ib_quota += perf->ib_quota;

			if (perf->mdp_clk_rate > clk_rate)
				clk_rate = perf->mdp_clk_rate;
		}
	}
	if (flags & MDSS_MDP_PERF_UPDATE_BUS) {
		bus_ab_quota = bus_ib_quota;
		__mdss_mdp_ctrl_perf_ovrd(mdata, &bus_ab_quota, &bus_ib_quota);
		pr_debug("update ab=%llu ib=%llu\n",
				bus_ab_quota, bus_ib_quota);
		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 HZ\n", clk_rate);
		mdss_mdp_set_clk_rate(clk_rate);
	}
	mutex_unlock(&mdss_mdp_ctl_lock);

	return 0;
}
Exemplo n.º 4
0
static void mdss_mdp_perf_mixer_update(struct mdss_mdp_mixer *mixer,
				       u32 *bus_ab_quota, u32 *bus_ib_quota,
				       u32 *clk_rate)
{
	struct mdss_mdp_pipe *pipe;
	struct mdss_panel_info *pinfo = NULL;
	int fps = DEFAULT_FRAME_RATE;
	u32 v_total;
	int i;
	u32 max_clk_rate = 0, ab_total = 0;
	u32 ib_max = 0, ib_max_smp = 0;
	u32 ib_quota[MDSS_MDP_MAX_STAGE];
	u32 v_region[MDSS_MDP_MAX_STAGE * 2];

	*bus_ab_quota = 0;
	*bus_ib_quota = 0;
	*clk_rate = 0;

	if (!mixer->rotator_mode) {
		if (mixer->type == MDSS_MDP_MIXER_TYPE_INTF) {
			pinfo = &mixer->ctl->panel_data->panel_info;
			fps = mdss_panel_get_framerate(pinfo);
			v_total = mdss_panel_get_vtotal(pinfo);

			if (pinfo->type == WRITEBACK_PANEL)
				pinfo = NULL;
		} else {
			v_total = mixer->height;
		}
		*clk_rate = mixer->width * v_total * fps;
		if (pinfo && pinfo->lcdc.v_back_porch < MDP_MIN_VBP)
			*clk_rate = MDSS_MDP_CLK_FUDGE_FACTOR(*clk_rate);

		if (!pinfo) {
			/* perf for bus writeback */
			*bus_ab_quota = fps * mixer->width * mixer->height * 3;
			*bus_ab_quota >>= MDSS_MDP_BUS_FACTOR_SHIFT;
			*bus_ib_quota = *bus_ab_quota;
		}
	}
Exemplo n.º 5
0
static void mdss_mdp_perf_calc_mixer(struct mdss_mdp_mixer *mixer,
		struct mdss_mdp_perf_params *perf)
{
	struct mdss_mdp_pipe *pipe;
	struct mdss_panel_info *pinfo = NULL;
	int fps = DEFAULT_FRAME_RATE;
	u32 v_total = 0;
	int i;
	u32 max_clk_rate = 0, ab_total = 0;
	u32 ib_max = 0;
	u32 ib_quota[MDSS_MDP_MAX_STAGE];
	u32 v_region[MDSS_MDP_MAX_STAGE * 2];
	u32 smp_bytes = 0;
	u64 smp_bw = 0;

	memset(perf, 0, sizeof(*perf));

	if (!mixer->rotator_mode) {
		if (mixer->type == MDSS_MDP_MIXER_TYPE_INTF) {
			pinfo = &mixer->ctl->panel_data->panel_info;
			fps = mdss_panel_get_framerate(pinfo);
			v_total = mdss_panel_get_vtotal(pinfo);

			if (pinfo->type == WRITEBACK_PANEL)
				pinfo = NULL;
		} else {
			v_total = mixer->height;
		}
		perf->mdp_clk_rate = mixer->width * v_total * fps;
		if (pinfo && pinfo->lcdc.v_back_porch < MDP_MIN_VBP)
			perf->mdp_clk_rate =
				MDSS_MDP_CLK_FUDGE_FACTOR(perf->mdp_clk_rate);

		if (!pinfo) {
			/* perf for bus writeback */
			perf->ab_quota = fps * mixer->width * mixer->height * 3;
			perf->ib_quota = perf->ab_quota;
		}
	}

	memset(ib_quota, 0, sizeof(u32) * MDSS_MDP_MAX_STAGE);
	memset(v_region, 0, sizeof(u32) * MDSS_MDP_MAX_STAGE * 2);

	for (i = 0; i < MDSS_MDP_MAX_STAGE; i++) {
		struct mdss_mdp_perf_params tmp;
		pipe = mixer->stage_pipe[i];
		if (pipe == NULL)
			continue;

		if (mdss_mdp_perf_calc_pipe(pipe, &tmp))
			continue;

		smp_bytes += mdss_mdp_smp_get_size(pipe);

		ab_total += tmp.ab_quota >> MDSS_MDP_BUS_FACTOR_SHIFT;
		ib_quota[i] = tmp.ib_quota >> MDSS_MDP_BUS_FACTOR_SHIFT;
		v_region[2*i] = pipe->dst.y;
		v_region[2*i + 1] = pipe->dst.y + pipe->dst.h;
		if (tmp.mdp_clk_rate > max_clk_rate)
			max_clk_rate = tmp.mdp_clk_rate;
	}

	/*
	 * Sort the v_region array so the total display area can be
	 * divided into individual regions. Check how many pipes fetch
	 * 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++) {
		int j;
		u32 ib_max_region = 0;
		u32 y0, y1;
		pr_debug("v_region[%d]%d\n", i, v_region[i]);
		if (v_region[i] == v_region[i-1])
			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++) {
			if (!ib_quota[j])
				continue;
			pipe = mixer->stage_pipe[j];
			if (mdss_mdp_perf_is_overlap
			    (y0, y1, pipe->dst.y, (pipe->dst.y + pipe->dst.h)))
				ib_max_region += ib_quota[j];
			pr_debug("v[%d](%d, %d)pipe[%d](%d,%d)quota=%d max=%d\n",
				i, y0, y1, j, pipe->dst.y,
				pipe->dst.y + pipe->dst.h, ib_quota[j],
				ib_max_region);
		}
		ib_max = max(ib_max, ib_max_region);
	}

	perf->ab_quota += ab_total << MDSS_MDP_BUS_FACTOR_SHIFT;
	perf->ib_quota += ib_max << MDSS_MDP_BUS_FACTOR_SHIFT;
	if (max_clk_rate > perf->mdp_clk_rate)
		perf->mdp_clk_rate = max_clk_rate;

	if (pinfo) {
		int vbp;

		/*
		 * need to be able to at least fill the shared memory pool
		 * during blanking period
		 */
		vbp = pinfo->lcdc.v_back_porch + pinfo->lcdc.v_pulse_width;
		smp_bw = smp_bytes * v_total * fps;
		do_div(smp_bw, vbp);

		if (smp_bw > perf->ib_quota) {
			pr_debug("replacing ib_quota=%llu with smp_bw=%llu\n",
					perf->ib_quota, smp_bw);
			perf->ib_quota = smp_bw;
		}
	}

	pr_debug("final mixer=%d clk_rate=%u bus ab=%llu ib=%llu smp=%llu\n",
			mixer->num, perf->mdp_clk_rate,
			perf->ab_quota, perf->ib_quota, smp_bw);
}