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

Commit ea77bf01 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: mdss: update panel timings in upstream driver during vblank"

parents a794ce70 706f221c
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -97,6 +97,14 @@ struct mdss_intr {
	spinlock_t lock;
};

struct simplified_prefill_factors {
	u32 fmt_mt_nv12_factor;
	u32 fmt_mt_factor;
	u32 fmt_linear_factor;
	u32 scale_factor;
	u32 xtra_ff_factor;
};

struct mdss_prefill_data {
	u32 ot_bytes;
	u32 y_buf_bytes;
@@ -105,6 +113,7 @@ struct mdss_prefill_data {
	u32 post_scaler_pixels;
	u32 pp_pixels;
	u32 fbc_lines;
	struct simplified_prefill_factors prefill_factors;
};

struct mdss_mdp_ppb {
@@ -163,6 +172,7 @@ enum mdss_qos_settings {
	MDSS_QOS_CDP,
	MDSS_QOS_OTLIM,
	MDSS_QOS_PER_PIPE_LUT,
	MDSS_QOS_SIMPLIFIED_PREFILL,
	MDSS_QOS_MAX,
};

+15 −2
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@
#define CREATE_TRACE_POINTS
#include "mdss_debug.h"
#include "mdss_smmu.h"
#include "mdss_mdp.h"

#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
#define MDSS_FB_NUM 3
@@ -1448,6 +1449,9 @@ static int mdss_fb_blank_unblank(struct msm_fb_data_type *mfd)
	}

	if (mfd->mdp.on_fnc) {
		struct mdss_panel_info *panel_info = mfd->panel_info;
		struct fb_var_screeninfo *var = &mfd->fbi->var;

		ret = mfd->mdp.on_fnc(mfd);
		if (ret) {
			mdss_fb_stop_disp_thread(mfd);
@@ -1461,6 +1465,13 @@ static int mdss_fb_blank_unblank(struct msm_fb_data_type *mfd)
		mfd->update.is_suspend = 0;
		mutex_unlock(&mfd->update.lock);

		/*
		 * Panel info can change depending in the information
		 * programmed in the controller.
		 * Update this info in the upstream structs.
		 */
		mdss_panelinfo_to_fb_var(panel_info, var);

		/* Start the work thread to signal idle time */
		if (mfd->idle_time)
			schedule_delayed_work(&mfd->idle_notify_work,
@@ -3096,8 +3107,10 @@ static void mdss_panelinfo_to_fb_var(struct mdss_panel_info *pinfo,

	var->xres = mdss_fb_get_panel_xres(&pdata->panel_info);
	var->yres = pinfo->yres;
	var->lower_margin = pinfo->lcdc.v_front_porch;
	var->upper_margin = pinfo->lcdc.v_back_porch;
	var->lower_margin = pinfo->lcdc.v_front_porch -
		pinfo->prg_fet;
	var->upper_margin = pinfo->lcdc.v_back_porch +
		pinfo->prg_fet;
	var->vsync_len = pinfo->lcdc.v_pulse_width;
	var->right_margin = pinfo->lcdc.h_front_porch;
	var->left_margin = pinfo->lcdc.h_back_porch;
+25 −0
Original line number Diff line number Diff line
@@ -1051,6 +1051,15 @@ static u32 mdss_get_props(void)
	return props;
}

void mdss_mdp_init_default_prefill_factors(struct mdss_data_type *mdata)
{
	mdata->prefill_data.prefill_factors.fmt_mt_nv12_factor = 8;
	mdata->prefill_data.prefill_factors.fmt_mt_factor = 4;
	mdata->prefill_data.prefill_factors.fmt_linear_factor = 1;
	mdata->prefill_data.prefill_factors.scale_factor = 1;
	mdata->prefill_data.prefill_factors.xtra_ff_factor = 2;
}

static void mdss_mdp_hw_rev_caps_init(struct mdss_data_type *mdata)
{

@@ -1078,9 +1087,11 @@ static void mdss_mdp_hw_rev_caps_init(struct mdss_data_type *mdata)
		set_bit(MDSS_QOS_CDP, mdata->mdss_qos_map);
		set_bit(MDSS_QOS_OTLIM, mdata->mdss_qos_map);
		set_bit(MDSS_QOS_PER_PIPE_LUT, mdata->mdss_qos_map);
		set_bit(MDSS_QOS_SIMPLIFIED_PREFILL, mdata->mdss_qos_map);
		set_bit(MDSS_CAPS_YUV_CONFIG, mdata->mdss_caps_map);
		set_bit(MDSS_CAPS_SCM_RESTORE_NOT_REQUIRED,
			mdata->mdss_caps_map);
		mdss_mdp_init_default_prefill_factors(mdata);
		break;
	case MDSS_MDP_HW_REV_105:
	case MDSS_MDP_HW_REV_109:
@@ -1398,6 +1409,20 @@ static ssize_t mdss_mdp_show_capabilities(struct device *dev,
	SPRINT("smp_mb_per_pipe=%d\n", mdata->smp_mb_per_pipe);
	SPRINT("max_downscale_ratio=%d\n", MAX_DOWNSCALE_RATIO);
	SPRINT("max_upscale_ratio=%d\n", MAX_UPSCALE_RATIO);

	if (test_bit(MDSS_QOS_SIMPLIFIED_PREFILL, mdata->mdss_qos_map)) {
		SPRINT("fmt_mt_nv12_factor=%d\n",
			mdata->prefill_data.prefill_factors.fmt_mt_nv12_factor);
		SPRINT("fmt_mt_factor=%d\n",
			mdata->prefill_data.prefill_factors.fmt_mt_factor);
		SPRINT("fmt_linear_factor=%d\n",
			mdata->prefill_data.prefill_factors.fmt_linear_factor);
		SPRINT("scale_factor=%d\n",
			mdata->prefill_data.prefill_factors.scale_factor);
		SPRINT("xtra_ff_factor=%d\n",
			mdata->prefill_data.prefill_factors.xtra_ff_factor);
	}

	if (mdata->props)
		SPRINT("props=%d", mdata->props);
	if (mdata->max_bw_low)
+0 −1
Original line number Diff line number Diff line
@@ -304,7 +304,6 @@ struct mdss_mdp_ctl {
	void *priv_data;
	void *intf_ctx[2];
	u32 wb_type;
	u32 prg_fet;

	struct mdss_mdp_writeback *wb;

+100 −13
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ static inline u64 apply_inverse_fudge_factor(u64 val,
static DEFINE_MUTEX(mdss_mdp_ctl_lock);

static inline int __mdss_mdp_ctl_get_mixer_off(struct mdss_mdp_mixer *mixer);
static u32 mdss_mdp_get_vbp_factor_max(struct mdss_mdp_ctl *ctl);

static inline u32 mdss_mdp_get_pclk_rate(struct mdss_mdp_ctl *ctl)
{
@@ -623,6 +624,59 @@ u32 mdss_apply_overhead_factors(u32 quota, bool is_nrt,
	return quota;
}

u64 mdss_mdp_perf_calc_simplified_prefill(struct mdss_mdp_pipe *pipe,
	u32 v_total, u32 fps, struct mdss_mdp_ctl *ctl)
{
	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
	struct simplified_prefill_factors *pfactors =
			&mdata->prefill_data.prefill_factors;
	u64 prefill_per_pipe = 0;
	u32 prefill_lines = pfactors->xtra_ff_factor;


	/* do not calculate prefill for command mode */
	if (!ctl->is_video_mode)
		goto exit;

	prefill_per_pipe = pipe->src.w * pipe->src_fmt->bpp;

	/* format factors */
	if (mdss_mdp_is_tile_format(pipe->src_fmt)) {
		if (mdss_mdp_is_nv12_format(pipe->src_fmt))
			prefill_lines += pfactors->fmt_mt_nv12_factor;
		else
			prefill_lines += pfactors->fmt_mt_factor;
	} else {
		prefill_lines += pfactors->fmt_linear_factor;
	}

	/* scaling factors */
	if (pipe->src.h > pipe->dst.h) {
		prefill_lines += pfactors->scale_factor;

		prefill_per_pipe = fudge_factor(prefill_per_pipe,
			DECIMATED_DIMENSION(pipe->src.h, pipe->vert_deci),
			pipe->dst.h);
	}

	prefill_per_pipe *= prefill_lines * mdss_mdp_get_vbp_factor_max(ctl);

	pr_debug("pipe src: %dx%d bpp:%d\n",
		pipe->src.w, pipe->src.h, pipe->src_fmt->bpp);
	pr_debug("ff_factor:%d mt_nv12:%d mt:%d\n",
		pfactors->xtra_ff_factor,
		(mdss_mdp_is_tile_format(pipe->src_fmt) &&
		mdss_mdp_is_nv12_format(pipe->src_fmt)) ?
		pfactors->fmt_mt_nv12_factor : 0,
		mdss_mdp_is_tile_format(pipe->src_fmt) ?
		pfactors->fmt_mt_factor : 0);
	pr_debug("pipe prefill:%llu lines:%d\n",
		prefill_per_pipe, prefill_lines);

exit:
	return prefill_per_pipe;
}

/**
 * mdss_mdp_perf_calc_pipe() - calculate performance numbers required by pipe
 * @pipe:	Source pipe struct containing updated pipe params
@@ -773,6 +827,13 @@ int mdss_mdp_perf_calc_pipe(struct mdss_mdp_pipe *pipe,
		mixer->ctl->disable_prefill ||
		(pipe->flags & MDP_SOLID_FILL)) {
		perf->prefill_bytes = 0;
		perf->bw_prefill = 0;
		goto exit;
	}

	if (test_bit(MDSS_QOS_SIMPLIFIED_PREFILL, mdata->mdss_qos_map)) {
		perf->bw_prefill = mdss_mdp_perf_calc_simplified_prefill(pipe,
			v_total, fps, mixer->ctl);
		goto exit;
	}

@@ -810,9 +871,9 @@ int mdss_mdp_perf_calc_pipe(struct mdss_mdp_pipe *pipe,
			mdss_mdp_perf_calc_pipe_prefill_cmd(&prefill_params);

exit:
	pr_debug("mixer=%d pnum=%d clk_rate=%u bw_overlap=%llu prefill=%d %s\n",
	pr_debug("mixer=%d pnum=%d clk_rate=%u bw_overlap=%llu bw_prefill=%llu (%d) %s\n",
		 mixer->num, pipe->num, perf->mdp_clk_rate, perf->bw_overlap,
		 perf->prefill_bytes, mdata->disable_prefill ?
		 perf->bw_prefill, perf->prefill_bytes, mdata->disable_prefill ?
		 "prefill is disabled" : "");

	return 0;
@@ -843,7 +904,7 @@ static void mdss_mdp_perf_calc_mixer(struct mdss_mdp_mixer *mixer,
	u64 bw_overlap[MAX_PIPES_PER_LM] = { 0 };
	u64 bw_overlap_async = 0;
	u32 v_region[MAX_PIPES_PER_LM * 2] = { 0 };
	u32 prefill_bytes = 0;
	u32 prefill_val = 0;
	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
	bool apply_fudge = true;
	struct mdss_mdp_format_params *fmt;
@@ -965,8 +1026,6 @@ static void mdss_mdp_perf_calc_mixer(struct mdss_mdp_mixer *mixer,
		bitmap_or(perf->bw_vote_mode, perf->bw_vote_mode,
			tmp.bw_vote_mode, MDSS_MDP_BW_MODE_MAX);

		prefill_bytes += tmp.prefill_bytes;

		/*
		 * for async layers, the overlap calculation is skipped
		 * and the bandwidth is added at the end, accounting for
@@ -986,6 +1045,11 @@ static void mdss_mdp_perf_calc_mixer(struct mdss_mdp_mixer *mixer,

		if (tmp.mdp_clk_rate > max_clk_rate)
			max_clk_rate = tmp.mdp_clk_rate;

		if (test_bit(MDSS_QOS_SIMPLIFIED_PREFILL, mdata->mdss_qos_map))
			prefill_val += tmp.bw_prefill;
		else
			prefill_val += tmp.prefill_bytes;
	}

	/*
@@ -1020,7 +1084,11 @@ static void mdss_mdp_perf_calc_mixer(struct mdss_mdp_mixer *mixer,
	}

	perf->bw_overlap += bw_overlap_max + bw_overlap_async;
	perf->prefill_bytes += prefill_bytes;

	if (test_bit(MDSS_QOS_SIMPLIFIED_PREFILL, mdata->mdss_qos_map))
		perf->bw_prefill += prefill_val;
	else
		perf->prefill_bytes += prefill_val;

	if (max_clk_rate > perf->mdp_clk_rate)
		perf->mdp_clk_rate = max_clk_rate;
@@ -1028,7 +1096,7 @@ static void mdss_mdp_perf_calc_mixer(struct mdss_mdp_mixer *mixer,
exit:
	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, prefill_val,
		*(perf->bw_vote_mode));
}

@@ -1105,7 +1173,7 @@ static u32 mdss_mdp_get_vbp_factor(struct mdss_mdp_ctl *ctl)
	fps = mdss_panel_get_framerate(pinfo);
	v_total = mdss_panel_get_vtotal(pinfo);
	vbp = pinfo->lcdc.v_back_porch + pinfo->lcdc.v_pulse_width;
	vbp += ctl->prg_fet;
	vbp += pinfo->prg_fet;

	vbp_fac = (vbp) ? fps * v_total / vbp : 0;
	pr_debug("vbp_fac=%d vbp=%d v_total=%d\n", vbp_fac, vbp, v_total);
@@ -1127,6 +1195,11 @@ static u32 mdss_mdp_get_vbp_factor_max(struct mdss_mdp_ctl *ctl)
		struct mdss_mdp_ctl *ctl = mdata->ctl_off + i;
		u32 vbp_fac;

		/* skip command mode interfaces */
		if (test_bit(MDSS_QOS_SIMPLIFIED_PREFILL, mdata->mdss_qos_map)
				&& !ctl->is_video_mode)
			continue;

		if (mdss_mdp_ctl_is_power_on(ctl)) {
			vbp_fac = mdss_mdp_get_vbp_factor(ctl);
			vbp_max = max(vbp_max, vbp_fac);
@@ -1165,6 +1238,7 @@ static void __mdss_mdp_perf_calc_ctl_helper(struct mdss_mdp_ctl *ctl,
		u32 flags)
{
	struct mdss_mdp_perf_params tmp;
	struct mdss_data_type *mdata = ctl->mdata;

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

@@ -1177,9 +1251,13 @@ static void __mdss_mdp_perf_calc_ctl_helper(struct mdss_mdp_ctl *ctl,

		perf->max_per_pipe_ib = tmp.max_per_pipe_ib;
		perf->bw_overlap += tmp.bw_overlap;
		perf->prefill_bytes += tmp.prefill_bytes;
		perf->mdp_clk_rate = tmp.mdp_clk_rate;
		perf->bw_writeback += tmp.bw_writeback;

		if (test_bit(MDSS_QOS_SIMPLIFIED_PREFILL, mdata->mdss_qos_map))
			perf->bw_prefill += tmp.bw_prefill;
		else
			perf->prefill_bytes += tmp.prefill_bytes;
	}

	if (ctl->mixer_right) {
@@ -1192,11 +1270,15 @@ static void __mdss_mdp_perf_calc_ctl_helper(struct mdss_mdp_ctl *ctl,
		perf->max_per_pipe_ib = max(perf->max_per_pipe_ib,
			tmp.max_per_pipe_ib);
		perf->bw_overlap += tmp.bw_overlap;
		perf->prefill_bytes += tmp.prefill_bytes;
		perf->bw_writeback += tmp.bw_writeback;
		if (tmp.mdp_clk_rate > perf->mdp_clk_rate)
			perf->mdp_clk_rate = tmp.mdp_clk_rate;

		if (test_bit(MDSS_QOS_SIMPLIFIED_PREFILL, mdata->mdss_qos_map))
			perf->bw_prefill += tmp.bw_prefill;
		else
			perf->prefill_bytes += tmp.prefill_bytes;

		if (ctl->intf_type) {
			u32 clk_rate = mdss_mdp_get_pclk_rate(ctl);
			/* minimum clock rate due to inefficiency in 3dmux */
@@ -1210,7 +1292,8 @@ static void __mdss_mdp_perf_calc_ctl_helper(struct mdss_mdp_ctl *ctl,
	if (perf->bw_overlap == 0)
		perf->bw_overlap = SZ_16M;

	if (ctl->intf_type != MDSS_MDP_NO_INTF) {
	if (!test_bit(MDSS_QOS_SIMPLIFIED_PREFILL, mdata->mdss_qos_map) &&
		(ctl->intf_type != MDSS_MDP_NO_INTF)) {
		u32 vbp_fac = mdss_mdp_get_vbp_factor_max(ctl);

		perf->bw_prefill = perf->prefill_bytes;
@@ -1368,8 +1451,12 @@ int mdss_mdp_perf_bw_check_pipe(struct mdss_mdp_perf_params *perf,
	if (ctl->intf_type == MDSS_MDP_NO_INTF)
		return 0;

	if (test_bit(MDSS_QOS_SIMPLIFIED_PREFILL, mdata->mdss_qos_map)) {
		prefill_bw = perf->bw_prefill;
	} else {
		vbp_fac = mdss_mdp_get_vbp_factor_max(ctl);
		prefill_bw = perf->prefill_bytes * vbp_fac;
	}
	pipe_bw = max(prefill_bw, perf->bw_overlap);
	pr_debug("prefill=%llu, vbp_fac=%u, overlap=%llu\n",
			prefill_bw, vbp_fac, perf->bw_overlap);
Loading