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

Commit e02de095 authored by Jeykumar Sankaran's avatar Jeykumar Sankaran Committed by Jeevan Shriram
Browse files

msm: mdss: Add support for concurrent writeback



This change adds support for concurrent writeback in supported
targets. The client requests for concurrent writeback by
selecting the data point in output buffer flags.

Change-Id: Ic108ce94daef4f96d1fa27b4057e49c01b9e9b8e
Signed-off-by: default avatarJeykumar Sankaran <jsanka@codeaurora.org>
Signed-off-by: default avatarIngrid Gallardo <ingridg@codeaurora.org>
parent 198fb282
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -174,6 +174,7 @@ enum mdss_hw_capabilities {
	MDSS_CAPS_QSEED3,
	MDSS_CAPS_DEST_SCALER,
	MDSS_CAPS_10_BIT_SUPPORTED,
	MDSS_CAPS_CWB_SUPPORTED,
	MDSS_CAPS_MAX,
};

+12 −1
Original line number Diff line number Diff line
@@ -4374,8 +4374,19 @@ static int mdss_fb_atomic_commit_ioctl(struct fb_info *info,
		commit.commit_v1.output_layer = output_layer_user;
		rc = copy_to_user(argp, &commit,
			sizeof(struct mdp_layer_commit));
		if (rc)
		if (rc) {
			pr_err("copy to user for release & retire fence failed\n");
			goto err;
		}
	}

	if (output_layer_user) {
		rc = copy_to_user(&output_layer_user->buffer.fence,
			&output_layer->buffer.fence,
			sizeof(int));

		if (rc)
			pr_err("copy to user for output fence failed");
	}

err:
+4 −1
Original line number Diff line number Diff line
@@ -222,7 +222,7 @@ static struct mdss_mdp_irq mdp_irq_map[] = {
	{ MDSS_MDP_IRQ_TYPE_PING_PONG_AUTO_REF, 2, MDSS_MDP_INTR_PING_PONG_2_AUTOREFRESH_DONE, 0},
	{ MDSS_MDP_IRQ_TYPE_PING_PONG_AUTO_REF, 3, MDSS_MDP_INTR_PING_PONG_3_AUTOREFRESH_DONE, 0},
	{ MDSS_MDP_IRQ_TYPE_CWB_OVERFLOW, 2, MDSS_MDP_INTR2_PING_PONG_2_CWB_OVERFLOW, 1},
	{ MDSS_MDP_IRQ_TYPE_CWB_OVERFLOW, 3, MDSS_MDP_INTR2_PING_PONG_2_CWB_OVERFLOW, 1}
	{ MDSS_MDP_IRQ_TYPE_CWB_OVERFLOW, 3, MDSS_MDP_INTR2_PING_PONG_3_CWB_OVERFLOW, 1}
};

static struct intr_callback *mdp_intr_cb;
@@ -1838,6 +1838,7 @@ static void mdss_mdp_hw_rev_caps_init(struct mdss_data_type *mdata)
			mdata->mdss_caps_map);
		set_bit(MDSS_CAPS_QSEED3, mdata->mdss_caps_map);
		set_bit(MDSS_CAPS_DEST_SCALER, mdata->mdss_caps_map);
		set_bit(MDSS_CAPS_CWB_SUPPORTED, mdata->mdss_caps_map);
		mdss_mdp_init_default_prefill_factors(mdata);
		mdss_set_quirk(mdata, MDSS_QUIRK_DSC_RIGHT_ONLY_PU);
		mdss_set_quirk(mdata, MDSS_QUIRK_DSC_2SLICE_PU_THRPUT);
@@ -2346,6 +2347,8 @@ ssize_t mdss_mdp_show_capabilities(struct device *dev,
		SPRINT(" dest_scaler");
	if (mdata->has_separate_rotator)
		SPRINT(" separate_rotator");
	if (test_bit(MDSS_CAPS_CWB_SUPPORTED, mdata->mdss_caps_map))
		SPRINT(" concurrent_writeback");
	SPRINT("\n");
#undef SPRINT

+34 −0
Original line number Diff line number Diff line
@@ -339,6 +339,17 @@ struct mdss_mdp_ctl_intfs_ops {
	int (*update_lineptr)(struct mdss_mdp_ctl *ctl, bool enable);
};

struct mdss_mdp_cwb {
	struct mutex queue_lock;
	struct list_head data_queue;
	int valid;
	u32 wb_idx;
	struct mdp_output_layer *layer;
	void *priv_data;
	struct msm_sync_pt_data cwb_sync_pt_data;
	struct blocking_notifier_head notifier_head;
};

struct mdss_mdp_ctl {
	u32 num;
	char __iomem *base;
@@ -554,6 +565,13 @@ struct mdss_mdp_data {
	struct mdss_mdp_pipe *last_pipe;
};

struct mdss_mdp_wb_data {
	struct mdp_output_layer layer;
	struct mdss_mdp_data data;
	bool signal_required;
	struct list_head next;
};

struct pp_hist_col_info {
	u32 col_state;
	u32 col_en;
@@ -814,6 +832,10 @@ struct mdss_overlay_private {
	u32 bl_events;
	u32 ad_events;
	u32 ad_bl_events;

	struct mdss_mdp_cwb cwb;
	wait_queue_head_t wb_waitq;
	atomic_t wb_busy;
};

struct mdss_mdp_set_ot_params {
@@ -1453,6 +1475,14 @@ void *mdss_mdp_get_intf_base_addr(struct mdss_data_type *mdata,
		u32 interface_id);
int mdss_mdp_cmd_start(struct mdss_mdp_ctl *ctl);
int mdss_mdp_writeback_start(struct mdss_mdp_ctl *ctl);
void *mdss_mdp_writeback_get_ctx_for_cwb(struct mdss_mdp_ctl *ctl);
int mdss_mdp_writeback_prepare_cwb(struct mdss_mdp_ctl *ctl,
		struct mdss_mdp_writeback_arg *wb_arg);
int mdss_mdp_acquire_wb(struct mdss_mdp_ctl *ctl);
int mdss_mdp_cwb_validate(struct msm_fb_data_type *mfd,
		struct mdp_output_layer *layer);
int mdss_mdp_cwb_check_resource(struct mdss_mdp_ctl *ctl, u32 wb_idx);

int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd,
		struct mdp_display_commit *data);
struct mdss_mdp_data *mdss_mdp_overlay_buf_alloc(struct msm_fb_data_type *mfd,
@@ -1689,6 +1719,8 @@ void mdss_mdp_set_roi(struct mdss_mdp_ctl *ctl,
	struct mdss_rect *l_roi, struct mdss_rect *r_roi);
void mdss_mdp_mixer_update_pipe_map(struct mdss_mdp_ctl *master_ctl,
		int mixer_mux);
int mdss_mdp_wb_import_data(struct device *device,
		struct mdss_mdp_wb_data *wb_data);

void mdss_mdp_pipe_calc_pixel_extn(struct mdss_mdp_pipe *pipe);
void mdss_mdp_pipe_calc_qseed3_cfg(struct mdss_mdp_pipe *pipe);
@@ -1701,6 +1733,8 @@ int mdss_mdp_cmd_get_autorefresh_mode(struct mdss_mdp_ctl *ctl);
int mdss_mdp_ctl_cmd_set_autorefresh(struct mdss_mdp_ctl *ctl, int frame_cnt);
int mdss_mdp_ctl_cmd_get_autorefresh(struct mdss_mdp_ctl *ctl);
int mdss_mdp_pp_get_version(struct mdp_pp_feature_version *version);
int mdss_mdp_layer_pre_commit_cwb(struct msm_fb_data_type *mfd,
		struct mdp_layer_commit_v1 *commit);

struct mdss_mdp_ctl *mdss_mdp_ctl_alloc(struct mdss_data_type *mdata,
					       u32 off);
+104 −4
Original line number Diff line number Diff line
@@ -3314,6 +3314,100 @@ static int mdss_mdp_ctl_fbc_enable(int enable,
	return 0;
}

int mdss_mdp_cwb_setup(struct mdss_mdp_ctl *ctl)
{
	struct mdss_mdp_cwb *cwb = NULL;
	struct mdss_mdp_writeback *wb = NULL;
	struct mdss_overlay_private *mdp5_data = NULL;
	struct mdss_mdp_wb_data *cwb_data;
	struct mdss_mdp_writeback_arg wb_args;
	struct mdss_mdp_ctl *sctl = NULL;
	struct mdss_data_type *mdata = mdss_mdp_get_mdata();

	u32 opmode, data_point;
	int rc = 0;

	if (!ctl->mfd)
		return -ENODEV;

	mdp5_data = mfd_to_mdp5_data(ctl->mfd);
	cwb = &mdp5_data->cwb;

	if (!cwb->valid)
		return rc;

	/* Wait for previous CWB job to complete */
	if (mdss_mdp_acquire_wb(ctl))
		return -EBUSY;

	wb = mdata->wb + cwb->wb_idx;
	wb->base = mdata->mdss_io.base + mdata->wb_offsets[cwb->wb_idx];
	ctl->wb = wb;

	/* Get new instance of writeback interface context */
	cwb->priv_data = mdss_mdp_writeback_get_ctx_for_cwb(ctl);
	if (cwb->priv_data == NULL) {
		pr_err("fail to get writeback context\n");
		rc = -ENOMEM;
		goto cwb_setup_done;
	}

	mutex_lock(&cwb->queue_lock);
	cwb_data = list_first_entry_or_null(&cwb->data_queue,
			struct mdss_mdp_wb_data, next);
	mutex_unlock(&cwb->queue_lock);
	if (cwb_data == NULL) {
		pr_err("no output buffer for cwb\n");
		rc = -ENOMEM;
		goto cwb_setup_done;
	}

	rc = mdss_mdp_data_map(&cwb_data->data, true, DMA_FROM_DEVICE);
	if (rc) {
		pr_err("fail to acquire CWB output buffer\n");
		goto cwb_setup_done;
	}

	memset(&wb_args, 0, sizeof(wb_args));
	wb_args.data = &cwb_data->data;

	rc =  mdss_mdp_writeback_prepare_cwb(ctl, &wb_args);
	if (rc) {
		pr_err("failed to writeback prepare cwb\n");
		goto cwb_setup_done;
	}

	/* Select MEM_SEL to WB */
	ctl->opmode |= MDSS_MDP_CTL_OP_WFD_MODE;
	sctl = mdss_mdp_get_split_ctl(ctl);
	if (sctl)
		sctl->opmode |= MDSS_MDP_CTL_OP_WFD_MODE;

	/* Select CWB data point */
	data_point = (cwb->layer->flags & MDP_COMMIT_CWB_DSPP) ? 0x4 : 0;
	writel_relaxed(data_point, mdata->mdp_base + mdata->ppb_ctl[2]);
	if (sctl)
		writel_relaxed(data_point + 1,
				mdata->mdp_base + mdata->ppb_ctl[3]);

	/* Flush WB */
	ctl->flush_bits |= BIT(16);

	opmode = mdss_mdp_ctl_read(ctl, MDSS_MDP_REG_CTL_TOP) | ctl->opmode;
	mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_TOP, opmode);
	if (sctl) {
		opmode = mdss_mdp_ctl_read(sctl, MDSS_MDP_REG_CTL_TOP) |
			sctl->opmode;
		mdss_mdp_ctl_write(sctl, MDSS_MDP_REG_CTL_TOP, opmode);
	}

cwb_setup_done:
	cwb->valid = 0;
	atomic_add_unless(&mdp5_data->wb_busy, -1, 0);

	return 0;
}

int mdss_mdp_ctl_setup(struct mdss_mdp_ctl *ctl)
{
	struct mdss_mdp_ctl *split_ctl;
@@ -5546,6 +5640,12 @@ int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg,
	    !bitmap_empty(mdata->bwc_enable_map, MAX_DRV_SUP_PIPES))
		mdss_mdp_bwcpanic_ctrl(mdata, true);

	ret = mdss_mdp_cwb_setup(ctl);
	if (ret)
		pr_warn("concurrent setup failed ctl=%d\n", ctl->num);

	ctl_flush_bits |= ctl->flush_bits;

	ATRACE_BEGIN("flush_kickoff");
	mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_FLUSH, ctl_flush_bits);
	if (sctl && sctl_flush_bits) {
Loading