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

Commit 76f4cff9 authored by Ingrid Gallardo's avatar Ingrid Gallardo Committed by Gerrit - the friendly Code Review server
Browse files

msm: mdss: add support for amortized prefill



Starting with sde 3.0, prefill bandwidth can
be amortized depending on the configuration.
This change adds support for this feature.

Change-Id: I501e11325365ec900a2ef8ee5bcbcd66f5647f64
Signed-off-by: default avatarIngrid Gallardo <ingridg@codeaurora.org>
parent 1d0805a9
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -110,6 +110,10 @@ struct mdss_prefill_data {
	u32 post_scaler_pixels;
	u32 pp_pixels;
	u32 fbc_lines;
	u32 ts_threshold;
	u32 ts_end;
	u32 ts_overhead;
	struct mult_factor ts_rate;
	struct simplified_prefill_factors prefill_factors;
};

@@ -185,6 +189,7 @@ enum mdss_qos_settings {
	MDSS_QOS_PER_PIPE_LUT,
	MDSS_QOS_SIMPLIFIED_PREFILL,
	MDSS_QOS_VBLANK_PANIC_CTRL,
	MDSS_QOS_TS_PREFILL,
	MDSS_QOS_MAX,
};

+17 −1
Original line number Diff line number Diff line
@@ -1391,6 +1391,14 @@ void mdss_mdp_init_default_prefill_factors(struct mdss_data_type *mdata)
	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;

	if (test_bit(MDSS_QOS_TS_PREFILL, mdata->mdss_qos_map)) {
		mdata->prefill_data.ts_threshold = 25;
		mdata->prefill_data.ts_end = 8;
		mdata->prefill_data.ts_rate.numer = 1;
		mdata->prefill_data.ts_rate.denom = 4;
		mdata->prefill_data.ts_overhead = 2;
	}
}

static void mdss_mdp_hw_rev_caps_init(struct mdss_data_type *mdata)
@@ -1517,7 +1525,7 @@ static void mdss_mdp_hw_rev_caps_init(struct mdss_data_type *mdata)
		mdata->per_pipe_ib_factor.denom = 5;
		mdata->apply_post_scale_bytes = false;
		mdata->hflip_buffer_reused = false;
		mdata->min_prefill_lines = 21;
		mdata->min_prefill_lines = 25;
		mdata->has_ubwc = true;
		mdata->pixel_ram_size = 50 * 1024;
		mdata->rects_per_sspp[MDSS_MDP_PIPE_TYPE_DMA] = 2;
@@ -1528,6 +1536,7 @@ static void mdss_mdp_hw_rev_caps_init(struct mdss_data_type *mdata)
		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_QOS_TS_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);
@@ -1991,6 +2000,13 @@ ssize_t mdss_mdp_show_capabilities(struct device *dev,
			mdata->prefill_data.prefill_factors.xtra_ff_factor);
	}

	if (test_bit(MDSS_QOS_TS_PREFILL, mdata->mdss_qos_map)) {
		SPRINT("amortizable_threshold=%d\n",
			mdata->prefill_data.ts_threshold);
		SPRINT("system_overhead_lines=%d\n",
			mdata->prefill_data.ts_overhead);
	}

	if (mdata->props)
		SPRINT("props=%d\n", mdata->props);
	if (mdata->max_bw_low)
+7 −0
Original line number Diff line number Diff line
@@ -1479,9 +1479,16 @@ int mdss_mdp_perf_bw_check(struct mdss_mdp_ctl *ctl,
		struct mdss_mdp_pipe **right_plist, int right_cnt);
int mdss_mdp_perf_bw_check_pipe(struct mdss_mdp_perf_params *perf,
		struct mdss_mdp_pipe *pipe);
u32 mdss_mdp_get_pipe_overlap_bw(struct mdss_mdp_pipe *pipe,
	struct mdss_rect *roi, u32 flags);
int mdss_mdp_get_panel_params(struct mdss_mdp_pipe *pipe,
	struct mdss_mdp_mixer *mixer, u32 *fps, u32 *v_total,
	u32 *h_total, u32 *xres);
int mdss_mdp_perf_calc_pipe(struct mdss_mdp_pipe *pipe,
	struct mdss_mdp_perf_params *perf, struct mdss_rect *roi,
	u32 flags);
bool mdss_mdp_is_amortizable_pipe(struct mdss_mdp_pipe *pipe,
	struct mdss_mdp_mixer *mixer, struct mdss_data_type *mdata);
u32 mdss_mdp_calc_latency_buf_bytes(bool is_yuv, bool is_bwc,
	bool is_tile, u32 src_w, u32 bpp, bool use_latency_buf_percentage,
	u32 smp_bytes, bool is_ubwc, bool is_nv12, bool is_hflip);
+166 −101
Original line number Diff line number Diff line
@@ -561,8 +561,13 @@ static u32 get_pipe_mdp_clk_rate(struct mdss_mdp_pipe *pipe,
	struct mdss_mdp_mixer *mixer;
	u32 rate, src_h;

	/*
	 * when doing vertical decimation lines will be skipped, hence there is
	 * no need to account for these lines in MDP clock or request bus
	 * bandwidth to fetch them.
	 */
	mixer = pipe->mixer_left;
	src_h = src.h >> pipe->vert_deci;
	src_h = DECIMATED_DIMENSION(src.h, pipe->vert_deci);

	if (mixer->rotator_mode) {

@@ -595,6 +600,144 @@ static u32 get_pipe_mdp_clk_rate(struct mdss_mdp_pipe *pipe,
	return rate;
}

static u32 mdss_mdp_get_rotator_fps(struct mdss_mdp_pipe *pipe)
{
	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
	u32 fps;

	if (pipe->src.w >= 3840 || pipe->src.h >= 3840)
		fps = ROTATOR_LOW_FRAME_RATE;
	else if (mdata->traffic_shaper_en)
		fps = DEFAULT_ROTATOR_FRAME_RATE;
	else if (pipe->frame_rate)
		fps = pipe->frame_rate;
	else
		fps = DEFAULT_FRAME_RATE;

	pr_debug("rotator fps:%d\n", fps);

	return fps;
}

int mdss_mdp_get_panel_params(struct mdss_mdp_pipe *pipe,
	struct mdss_mdp_mixer *mixer, u32 *fps, u32 *v_total,
	u32 *h_total, u32 *xres)
{

	if (mixer->rotator_mode) {
		*fps = mdss_mdp_get_rotator_fps(pipe);
	} else if (mixer->type == MDSS_MDP_MIXER_TYPE_INTF) {
		struct mdss_panel_info *pinfo;

		if (!mixer->ctl)
			return -EINVAL;

		pinfo = &mixer->ctl->panel_data->panel_info;
		if (pinfo->type == MIPI_VIDEO_PANEL) {
			*fps = pinfo->panel_max_fps;
			*v_total = pinfo->panel_max_vtotal;
		} else {
			*fps = mdss_panel_get_framerate(pinfo);
			*v_total = mdss_panel_get_vtotal(pinfo);
		}
		*xres = get_panel_width(mixer->ctl);
		*h_total = mdss_panel_get_htotal(pinfo, false);

		if (is_pingpong_split(mixer->ctl->mfd))
			*h_total += mdss_panel_get_htotal(
				&mixer->ctl->panel_data->next->panel_info,
				false);
	} else {
		*v_total = mixer->height;
		*xres = mixer->width;
		*h_total = mixer->width;
	}

	return 0;
}

u32 mdss_mdp_get_pipe_overlap_bw(struct mdss_mdp_pipe *pipe,
	struct mdss_rect *roi, u32 flags)
{
	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
	struct mdss_mdp_mixer *mixer = pipe->mixer_left;
	struct mdss_rect src, dst;
	u32 v_total, fps, h_total, xres;
	u32 quota, src_h;

	if (mdss_mdp_get_panel_params(pipe, mixer, &fps, &v_total,
			&h_total, &xres)) {
		pr_err(" error retreiving the panel params!\n");
		return -EINVAL;
	}

	dst = pipe->dst;
	src = pipe->src;

	/* crop rectangles */
	if (roi && !mixer->ctl->is_video_mode && !pipe->src_split_req)
		mdss_mdp_crop_rect(&src, &dst, roi);

	/*
	 * when doing vertical decimation lines will be skipped, hence there is
	 * no need to account for these lines in MDP clock or request bus
	 * bandwidth to fetch them.
	 */
	src_h = DECIMATED_DIMENSION(src.h, pipe->vert_deci);

	quota = fps * src.w * src_h;

	if (pipe->src_fmt->chroma_sample == MDSS_MDP_CHROMA_420)
		/*
		 * with decimation, chroma is not downsampled, this means we
		 * need to allocate bw for extra lines that will be fetched
		 */
		if (pipe->vert_deci)
			quota *= 2;
		else
			quota = (quota * 3) / 2;
	else
		quota *= pipe->src_fmt->bpp;

	if (mixer->rotator_mode) {
		if (test_bit(MDSS_QOS_OVERHEAD_FACTOR,
				mdata->mdss_qos_map)) {
			/* rotator read */
			quota = apply_comp_ratio_factor(quota,
				pipe->src_fmt, &pipe->comp_ratio);
			/*
			 * rotator write: here we are using src_fmt since
			 * current implementation only supports calculate
			 * bandwidth based in the source parameters.
			 * The correct fine-tuned calculation should use
			 * destination format and destination rectangles to
			 * calculate the bandwidth, but leaving this
			 * calculation as per current support.
			 */
			quota += apply_comp_ratio_factor(quota,
				pipe->src_fmt, &pipe->comp_ratio);
		} else {
			quota *= 2; /* bus read + write */
		}
	} else {

		quota = mult_frac(quota, v_total, dst.h);
		if (!mixer->ctl->is_video_mode)
			quota = mult_frac(quota, h_total, xres);

		if (test_bit(MDSS_QOS_OVERHEAD_FACTOR,
				mdata->mdss_qos_map))
			quota = apply_comp_ratio_factor(quota,
				pipe->src_fmt, &pipe->comp_ratio);
	}

	pr_debug("quota:%d src.w:%d src.h%d comp:[%d, %d]\n",
		quota, src.w, src_h, pipe->comp_ratio.numer,
		pipe->comp_ratio.denom);

	return quota;
}

static inline bool validate_comp_ratio(struct mult_factor *factor)
{
	return factor->numer && factor->denom;
@@ -618,25 +761,6 @@ u32 apply_comp_ratio_factor(u32 quota,
	return quota;
}

static u32 mdss_mdp_get_rotator_fps(struct mdss_mdp_pipe *pipe)
{
	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
	u32 fps = DEFAULT_FRAME_RATE;

	if (pipe->frame_rate)
		fps = pipe->frame_rate;

	if (mdata->traffic_shaper_en)
		fps = DEFAULT_ROTATOR_FRAME_RATE;

	if (pipe->src.w >= 3840 || pipe->src.h >= 3840)
		fps = ROTATOR_LOW_FRAME_RATE;

	pr_debug("rotator fps:%d\n", fps);

	return fps;
}

u64 mdss_mdp_perf_calc_simplified_prefill(struct mdss_mdp_pipe *pipe,
	u32 v_total, u32 fps, struct mdss_mdp_ctl *ctl)
{
@@ -713,13 +837,14 @@ exit:
 * fetches (bandwidth requirement) and processes data through MDP pipeline
 * (MDP clock requirement) based on frame size and scaling requirements.
 */

int mdss_mdp_perf_calc_pipe(struct mdss_mdp_pipe *pipe,
	struct mdss_mdp_perf_params *perf, struct mdss_rect *roi,
	u32 flags)
{
	struct mdss_mdp_mixer *mixer;
	int fps = DEFAULT_FRAME_RATE;
	u32 quota, v_total = 0, src_h, xres = 0, h_total = 0;
	u32 v_total = 0, src_h, xres = 0, h_total = 0;
	struct mdss_rect src, dst;
	bool is_fbc = false;
	struct mdss_mdp_prefill_params prefill_params;
@@ -734,105 +859,45 @@ int mdss_mdp_perf_calc_pipe(struct mdss_mdp_pipe *pipe,
	dst = pipe->dst;
	src = pipe->src;

	if (mixer->rotator_mode) {
		fps = mdss_mdp_get_rotator_fps(pipe);
	} else if (mixer->type == MDSS_MDP_MIXER_TYPE_INTF) {
		struct mdss_panel_info *pinfo;
	/*
	 * when doing vertical decimation lines will be skipped, hence there is
	 * no need to account for these lines in MDP clock or request bus
	 * bandwidth to fetch them.
	 */
	src_h = DECIMATED_DIMENSION(src.h, pipe->vert_deci);

		if (!mixer->ctl)
	if (mdss_mdp_get_panel_params(pipe, mixer, &fps, &v_total,
			&h_total, &xres)) {
		pr_err(" error retreiving the panel params!\n");
		return -EINVAL;

		pinfo = &mixer->ctl->panel_data->panel_info;
		if (pinfo->type == MIPI_VIDEO_PANEL) {
			fps = pinfo->panel_max_fps;
			v_total = pinfo->panel_max_vtotal;
		} else {
			fps = mdss_panel_get_framerate(pinfo);
			v_total = mdss_panel_get_vtotal(pinfo);
	}
		xres = get_panel_width(mixer->ctl);
		is_fbc = pinfo->fbc.enabled;
		h_total = mdss_panel_get_htotal(pinfo, false);

		if (is_pingpong_split(mixer->ctl->mfd))
			h_total += mdss_panel_get_htotal(
				&mixer->ctl->panel_data->next->panel_info,
				false);
	} else {
		v_total = mixer->height;
		xres = mixer->width;
		h_total = mixer->width;
	if (mixer->type == MDSS_MDP_MIXER_TYPE_INTF) {
		if (!mixer->ctl)
			return -EINVAL;
		is_fbc = mixer->ctl->panel_data->panel_info.fbc.enabled;
	}

	mixer->ctl->frame_rate = fps;

	/* crop rectangles */
	if (roi && !mixer->ctl->is_video_mode && !pipe->src_split_req)
		mdss_mdp_crop_rect(&src, &dst, roi);

	pr_debug("v_total=%d, xres=%d fps=%d\n", v_total, xres, fps);

	/*
	 * when doing vertical decimation lines will be skipped, hence there is
	 * no need to account for these lines in MDP clock or request bus
	 * bandwidth to fetch them.
	 */
	src_h = DECIMATED_DIMENSION(src.h, pipe->vert_deci);

	quota = fps * src.w * src_h;

	pr_debug("src(w,h)(%d,%d) dst(w,h)(%d,%d) dst_y=%d bpp=%d yuv=%d\n",
		 pipe->src.w, src_h, pipe->dst.w, pipe->dst.h, pipe->dst.y,
		 pipe->src_fmt->bpp, pipe->src_fmt->is_yuv);

	if (pipe->src_fmt->chroma_sample == MDSS_MDP_CHROMA_420)
		/*
		 * with decimation, chroma is not downsampled, this means we
		 * need to allocate bw for extra lines that will be fetched
		 */
		if (pipe->vert_deci)
			quota *= 2;
		else
			quota = (quota * 3) / 2;
	else
		quota *= pipe->src_fmt->bpp;

	if (mixer->rotator_mode) {
		if (test_bit(MDSS_QOS_OVERHEAD_FACTOR,
				mdata->mdss_qos_map)) {
			/* rotator read */
			quota = apply_comp_ratio_factor(quota,
				pipe->src_fmt, &pipe->comp_ratio);
			/*
			 * rotator write: here we are using src_fmt since
			 * current implementation only supports calculate
			 * bandwidth based in the source parameters.
			 * The correct fine-tuned calculation should use
			 * destination format and destination rectangles to
			 * calculate the bandwidth, but leaving this
			 * calculation as per current support.
			 */
			quota += apply_comp_ratio_factor(quota,
				pipe->src_fmt, &pipe->comp_ratio);
		} else {
			quota *= 2; /* bus read + write */
		}
	} else {

		quota = mult_frac(quota, v_total, dst.h);
		if (!mixer->ctl->is_video_mode)
			quota = mult_frac(quota, h_total, xres);

		if (test_bit(MDSS_QOS_OVERHEAD_FACTOR,
				mdata->mdss_qos_map))
			quota = apply_comp_ratio_factor(quota,
				pipe->src_fmt, &pipe->comp_ratio);
	}

	perf->bw_overlap = quota;
	perf->bw_overlap = mdss_mdp_get_pipe_overlap_bw(pipe, roi,
		flags);

	perf->mdp_clk_rate = get_pipe_mdp_clk_rate(pipe, src, dst,
		fps, v_total, flags);

	pr_debug("bw:%llu clk:%d\n", perf->bw_overlap,
		perf->mdp_clk_rate);

	if (pipe->flags & MDP_SOLID_FILL) {
		perf->bw_overlap = 0;
	}
+3 −0
Original line number Diff line number Diff line
@@ -250,6 +250,9 @@ enum mdss_mdp_sspp_chroma_samp_type {
#define MDSS_MDP_REG_SSPP_QOS_CTRL			0x06C
#define MDSS_MDP_REG_SSPP_CDP_CTRL			0x134
#define MDSS_MDP_REG_SSPP_UBWC_ERROR_STATUS		0x138
#define MDSS_MDP_REG_SSPP_TRAFFIC_SHAPER		0x130
#define MDSS_MDP_REG_SSPP_TRAFFIC_SHAPER_PREFILL	0x150
#define MDSS_MDP_REG_SSPP_TRAFFIC_SHAPER_REC1_PREFILL	0x154

#define MDSS_MDP_REG_SSPP_MULTI_REC_OP_MODE		0x170
#define MDSS_MDP_REG_SSPP_OUT_SIZE_REC1			0x160
Loading