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

Commit 47b71aee 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: Power collapse mdss vbif before going to suspend"

parents 877caa39 a46d83ce
Loading
Loading
Loading
Loading
+88 −55
Original line number Diff line number Diff line
@@ -154,52 +154,6 @@ static int mdss_mdp_parse_dt_ppb_off(struct platform_device *pdev);
static int mdss_mdp_parse_dt_cdm(struct platform_device *pdev);
static int mdss_mdp_parse_dt_dsc(struct platform_device *pdev);

/**
 * mdss_mdp_vbif_axi_halt() - Halt MDSS AXI ports
 * @mdata: pointer to the global mdss data structure.
 *
 * Check if MDSS AXI ports connected to RealTime(RT) VBIF are idle or not. If
 * not send a halt request and wait for it be idle.
 *
 * This function can be called during deep suspend, display off or for
 * debugging purposes. On success it should be assumed that AXI ports connected
 * to RT VBIF are in idle state and would not fetch any more data. This function
 * cannot be called from interrupt context.
 */
int mdss_mdp_vbif_axi_halt(struct mdss_data_type *mdata)
{
	bool is_idle;
	int rc = 0;
	u32 reg_val, idle_mask, status;

	idle_mask = BIT(4);
	if (mdata->axi_port_cnt == 2)
		idle_mask |= BIT(5);

	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON);
	reg_val = MDSS_VBIF_READ(mdata, MMSS_VBIF_AXI_HALT_CTRL1, false);

	is_idle = (reg_val & idle_mask) ? true : false;
	if (!is_idle) {
		pr_err("axi is not idle. halt_ctrl1=%d\n", reg_val);

		MDSS_VBIF_WRITE(mdata, MMSS_VBIF_AXI_HALT_CTRL0, 1, false);

		rc = readl_poll_timeout(mdata->vbif_io.base +
			MMSS_VBIF_AXI_HALT_CTRL1, status, (status & idle_mask),
			1000, AXI_HALT_TIMEOUT_US);
		if (rc == -ETIMEDOUT)
			pr_err("VBIF axi is not halting. TIMEDOUT.\n");
		else
			pr_debug("VBIF axi is halted\n");

		MDSS_VBIF_WRITE(mdata, MMSS_VBIF_AXI_HALT_CTRL0, 0, false);
	}
	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF);

	return rc;
}

u32 mdss_mdp_fb_stride(u32 fb_index, u32 xres, int bpp)
{
	/* The adreno GPU hardware requires that the pitch be aligned to
@@ -731,6 +685,86 @@ unsigned long mdss_mdp_get_clk_rate(u32 clk_idx)
	return clk_rate;
}

/**
 * __mdss_mdp_reg_access_clk_enable - Enable minimum MDSS clocks required
 * for register access
 */
static inline void __mdss_mdp_reg_access_clk_enable(
		struct mdss_data_type *mdata, bool enable)
{
	if (enable) {
		mdss_update_reg_bus_vote(mdata->reg_bus_clt,
				VOTE_INDEX_19_MHZ);
		mdss_mdp_clk_update(MDSS_CLK_AHB, 1);
		mdss_mdp_clk_update(MDSS_CLK_AXI, 1);
		mdss_mdp_clk_update(MDSS_CLK_MDP_CORE, 1);
	} else {
		mdss_mdp_clk_update(MDSS_CLK_MDP_CORE, 0);
		mdss_mdp_clk_update(MDSS_CLK_AXI, 0);
		mdss_mdp_clk_update(MDSS_CLK_AHB, 0);
		mdss_update_reg_bus_vote(mdata->reg_bus_clt,
				VOTE_INDEX_DISABLE);
	}
}

int __mdss_mdp_vbif_halt(struct mdss_data_type *mdata, bool is_nrt)
{
	int rc = 0;
	void __iomem *base;
	u32 halt_ack_mask = BIT(0), status;

	/* if not real time vbif */
	if (is_nrt)
		base = mdata->vbif_nrt_io.base;
	else
		base = mdata->vbif_io.base;

	if (!base) {
		/* some targets might not have a nrt port */
		goto vbif_done;
	}

	/* force vbif clock on */
	MDSS_VBIF_WRITE(mdata, MMSS_VBIF_CLKON, 1, is_nrt);

	/* request halt */
	MDSS_VBIF_WRITE(mdata, MMSS_VBIF_AXI_HALT_CTRL0, 1, is_nrt);

	rc = readl_poll_timeout(base +
			MMSS_VBIF_AXI_HALT_CTRL1, status, (status &
				halt_ack_mask),
			1000, AXI_HALT_TIMEOUT_US);
	if (rc == -ETIMEDOUT) {
		pr_err("VBIF axi is not halting. TIMEDOUT.\n");
		goto vbif_done;
	}

	pr_debug("VBIF axi is halted\n");

vbif_done:
	return rc;
}

/**
 * mdss_mdp_vbif_axi_halt() - Halt MDSS AXI ports
 * @mdata: pointer to the global mdss data structure.
 *
 * This function can be called during deep suspend, display off or for
 * debugging purposes. On success it should be assumed that AXI ports connected
 * to RT VBIF are in idle state and would not fetch any more data.
 */
static void mdss_mdp_vbif_axi_halt(struct mdss_data_type *mdata)
{
	__mdss_mdp_reg_access_clk_enable(mdata, true);

	/* real time ports */
	__mdss_mdp_vbif_halt(mdata, false);
	/* non-real time ports */
	__mdss_mdp_vbif_halt(mdata, true);

	__mdss_mdp_reg_access_clk_enable(mdata, false);
}

int mdss_iommu_ctrl(int enable)
{
	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
@@ -958,20 +992,14 @@ static void __mdss_restore_sec_cfg(struct mdss_data_type *mdata)

	pr_debug("restoring mdss secure config\n");

	mdss_update_reg_bus_vote(mdata->reg_bus_clt, VOTE_INDEX_19_MHZ);
	mdss_mdp_clk_update(MDSS_CLK_AHB, 1);
	mdss_mdp_clk_update(MDSS_CLK_AXI, 1);
	mdss_mdp_clk_update(MDSS_CLK_MDP_CORE, 1);
	__mdss_mdp_reg_access_clk_enable(mdata, true);

	ret = scm_restore_sec_cfg(SEC_DEVICE_MDSS, 0, &scm_ret);
	if (ret || scm_ret)
		pr_warn("scm_restore_sec_cfg failed %d %d\n",
				ret, scm_ret);

	mdss_mdp_clk_update(MDSS_CLK_AHB, 0);
	mdss_update_reg_bus_vote(mdata->reg_bus_clt, VOTE_INDEX_DISABLE);
	mdss_mdp_clk_update(MDSS_CLK_AXI, 0);
	mdss_mdp_clk_update(MDSS_CLK_MDP_CORE, 0);
	__mdss_mdp_reg_access_clk_enable(mdata, false);
}

static int mdss_mdp_gdsc_notifier_call(struct notifier_block *self,
@@ -981,8 +1009,13 @@ static int mdss_mdp_gdsc_notifier_call(struct notifier_block *self,

	mdata = container_of(self, struct mdss_data_type, gdsc_cb);

	if (event & REGULATOR_EVENT_ENABLE)
	if (event & REGULATOR_EVENT_ENABLE) {
		__mdss_restore_sec_cfg(mdata);
	} else if (event & REGULATOR_EVENT_PRE_DISABLE) {
		pr_debug("mdss gdsc is getting disabled\n");
		/* halt the vbif transactions */
		mdss_mdp_vbif_axi_halt(mdata);
	}

	return NOTIFY_OK;
}
+0 −1
Original line number Diff line number Diff line
@@ -1201,7 +1201,6 @@ void mdss_mdp_bwcpanic_ctrl(struct mdss_data_type *mdata, bool enable);
int mdss_mdp_pipe_destroy(struct mdss_mdp_pipe *pipe);
int mdss_mdp_pipe_queue_data(struct mdss_mdp_pipe *pipe,
			     struct mdss_mdp_data *src_data);
int mdss_mdp_vbif_axi_halt(struct mdss_data_type *mdata);

int mdss_mdp_data_check(struct mdss_mdp_data *data,
			struct mdss_mdp_plane_sizes *ps,