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

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

Merge "mdss: mdp3: Group together resource enable, simplifying xo shutdown"

parents a8a5ce6d 6286a5ab
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include "dsi_io_v2.h"
#include "dsi_host_v2.h"
#include "mdss_debug.h"
#include "mdp3.h"

#define DSI_POLL_SLEEP_US 1000
#define DSI_POLL_TIMEOUT_US 16000
@@ -971,7 +972,13 @@ int msm_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp)
		mutex_unlock(&ctrl->cmd_mutex);
		return ret;
	}

	/*
	 * mdss interrupt is generated in mdp core clock domain
	 * mdp clock need to be enabled to receive dsi interrupt
	 * also, axi bus bandwidth need since dsi controller will
	 * fetch dcs commands from axi bus
	 */
	mdp3_res_update(1, 1, MDP3_CLIENT_DMA_P);
	msm_dsi_clk_ctrl(&ctrl->panel_data, 1);

	if (0 == (req->flags & CMD_REQ_LP_MODE))
@@ -986,6 +993,7 @@ int msm_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp)
		dsi_set_tx_power_mode(1);

	msm_dsi_clk_ctrl(&ctrl->panel_data, 0);
	mdp3_res_update(0, 1, MDP3_CLIENT_DMA_P);

	mutex_unlock(&ctrl->cmd_mutex);
	return 0;
@@ -1431,13 +1439,16 @@ static int msm_dsi_clk_ctrl(struct mdss_panel_data *pdata, int enable)
						&byteclk_rate, &pclk_rate);
			msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, dsiclk_rate,
						byteclk_rate, pclk_rate);
			msm_dsi_prepare_clocks();
			msm_dsi_clk_enable();
		}
	} else {
		dsi_host_private->clk_count--;
		if (dsi_host_private->clk_count == 0) {
			msm_dsi_clear_irq(ctrl_pdata, ctrl_pdata->dsi_irq_mask);
			msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, 0, 0, 0);
			msm_dsi_clk_disable();
			msm_dsi_unprepare_clocks();
			msm_dsi_ahb_ctrl(0);
		}
	}
+131 −68
Original line number Diff line number Diff line
@@ -191,11 +191,11 @@ static irqreturn_t mdp3_irq_handler(int irq, void *ptr)
	u32 mdp_status = 0;

	spin_lock(&mdata->irq_lock);
	if (!mdata->irq_mask)
	if (!mdata->irq_mask) {
		pr_err("spurious interrupt\n");

	clk_enable(mdp3_res->clocks[MDP3_CLK_AHB]);
	clk_enable(mdp3_res->clocks[MDP3_CLK_CORE]);
		spin_unlock(&mdata->irq_lock);
		return IRQ_HANDLED;
	}

	mdp_status = MDP3_REG_READ(MDP3_REG_INTR_STATUS);
	mdp_interrupt = mdp_status;
@@ -211,9 +211,6 @@ static irqreturn_t mdp3_irq_handler(int irq, void *ptr)
	}
	MDP3_REG_WRITE(MDP3_REG_INTR_CLEAR, mdp_status);

	clk_disable(mdp3_res->clocks[MDP3_CLK_AHB]);
	clk_disable(mdp3_res->clocks[MDP3_CLK_CORE]);

	spin_unlock(&mdata->irq_lock);

	return IRQ_HANDLED;
@@ -281,19 +278,51 @@ void mdp3_irq_register(void)

	pr_debug("mdp3_irq_register\n");
	spin_lock_irqsave(&mdp3_res->irq_lock, flag);
	mdp3_res->irq_ref_cnt++;
	if (mdp3_res->irq_ref_cnt == 1) {
		MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, mdp3_res->irq_mask);
		enable_irq(mdp3_res->irq);
	}
	spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
}

void mdp3_irq_deregister(void)
{
	unsigned long flag;
	bool irq_enabled = true;

	pr_debug("mdp3_irq_deregister\n");
	spin_lock_irqsave(&mdp3_res->irq_lock, flag);
	memset(mdp3_res->irq_ref_count, 0, sizeof(u32) * MDP3_MAX_INTR);
	mdp3_res->irq_mask = 0;
	MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, 0);
	mdp3_res->irq_ref_cnt--;
	/* This can happen if suspend is called first */
	if (mdp3_res->irq_ref_cnt < 0) {
		irq_enabled = false;
		mdp3_res->irq_ref_cnt = 0;
	}
	if (mdp3_res->irq_ref_cnt == 0 && irq_enabled)
		disable_irq_nosync(mdp3_res->irq);
	spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
}

void mdp3_irq_suspend(void)
{
	unsigned long flag;
	bool irq_enabled = true;

	pr_debug("%s\n", __func__);
	spin_lock_irqsave(&mdp3_res->irq_lock, flag);
	mdp3_res->irq_ref_cnt--;
	if (mdp3_res->irq_ref_cnt < 0) {
		irq_enabled = false;
		mdp3_res->irq_ref_cnt = 0;
	}
	if (mdp3_res->irq_ref_cnt == 0 && irq_enabled) {
		MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, 0);
		disable_irq_nosync(mdp3_res->irq);
	}
	spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
}

@@ -403,6 +432,12 @@ int mdp3_bus_scale_set_quota(int client, u64 ab_quota, u64 ib_quota)
	}
	bus_handle->current_bus_idx = bus_idx;
	rc = msm_bus_scale_client_update_request(bus_handle->handle, bus_idx);

	if (!rc && ab_quota != 0 && ib_quota != 0) {
		bus_handle->restore_ab = ab_quota;
		bus_handle->restore_ib = ib_quota;
	}

	return rc;
}

@@ -425,10 +460,18 @@ static int mdp3_clk_update(u32 clk_idx, u32 enable)
	count = mdp3_res->clock_ref_count[clk_idx];
	if (count == 1 && enable) {
		pr_debug("clk=%d en=%d\n", clk_idx, enable);
		ret = clk_prepare(clk);
		if (ret) {
			pr_err("%s: Failed to prepare clock %d",
						__func__, clk_idx);
			mdp3_res->clock_ref_count[clk_idx]--;
			return ret;
		}
		ret = clk_enable(clk);
	} else if (count == 0) {
		pr_debug("clk=%d disable\n", clk_idx);
		clk_disable(clk);
		clk_unprepare(clk);
		ret = 0;
	} else if (count < 0) {
		pr_err("clk=%d count=%d\n", clk_idx, count);
@@ -580,54 +623,76 @@ int mdp3_clk_enable(int enable, int dsi_clk)
	return rc;
}

int mdp3_clk_prepare(void)
void mdp3_bus_bw_iommu_enable(int enable, int client)
{
	int rc = 0;
	struct mdp3_bus_handle_map *bus_handle;
	int client_idx;
	u64 ab, ib;
	int ref_cnt;

	mutex_lock(&mdp3_res->res_mutex);
	mdp3_res->clk_prepare_count++;
	if (mdp3_res->clk_prepare_count == 1) {
		rc = clk_prepare(mdp3_res->clocks[MDP3_CLK_AHB]);
		if (rc < 0)
			goto error0;
		rc = clk_prepare(mdp3_res->clocks[MDP3_CLK_CORE]);
		if (rc < 0)
			goto error1;
		rc = clk_prepare(mdp3_res->clocks[MDP3_CLK_VSYNC]);
		if (rc < 0)
			goto error2;
		rc = clk_prepare(mdp3_res->clocks[MDP3_CLK_DSI]);
		if (rc < 0)
			goto error3;
	if (client == MDP3_CLIENT_DMA_P) {
		client_idx  = MDP3_BUS_HANDLE_DMA;
	} else if (client == MDP3_CLIENT_PPP) {
		client_idx  = MDP3_BUS_HANDLE_PPP;
	} else {
		pr_err("invalid client %d\n", client);
		return;
	}
	mutex_unlock(&mdp3_res->res_mutex);
	return rc;

error3:
	clk_unprepare(mdp3_res->clocks[MDP3_CLK_VSYNC]);
error2:
	clk_unprepare(mdp3_res->clocks[MDP3_CLK_CORE]);
error1:
	clk_unprepare(mdp3_res->clocks[MDP3_CLK_AHB]);
error0:
	mdp3_res->clk_prepare_count--;
	bus_handle = &mdp3_res->bus_handle[client_idx];
	if (bus_handle->handle < 1) {
		pr_err("invalid bus handle %d\n", bus_handle->handle);
		return;
	}
	mutex_lock(&mdp3_res->res_mutex);
	if (enable)
		bus_handle->ref_cnt++;
	else
		bus_handle->ref_cnt--;
	ref_cnt = bus_handle->ref_cnt;
	mutex_unlock(&mdp3_res->res_mutex);
	return rc;

	if (enable && ref_cnt == 1) {
		if (mdp3_res->allow_iommu_update)
			mdp3_iommu_enable(client);
		ab = bus_handle->restore_ab;
		ib = bus_handle->restore_ib;
		mdp3_bus_scale_set_quota(client, ab, ib);
	} else if (!enable && ref_cnt == 0) {
		mdp3_bus_scale_set_quota(client, 0, 0);
		mdp3_iommu_disable(client);
	} else if (ref_cnt < 0) {
		pr_err("Ref count < 0, bus client=%d, ref_cnt=%d",
				client_idx, ref_cnt);
	}
}

void mdp3_clk_unprepare(void)
int mdp3_res_update(int enable, int dsi_clk, int client)
{
	mutex_lock(&mdp3_res->res_mutex);
	mdp3_res->clk_prepare_count--;
	if (mdp3_res->clk_prepare_count == 0) {
		clk_unprepare(mdp3_res->clocks[MDP3_CLK_AHB]);
		clk_unprepare(mdp3_res->clocks[MDP3_CLK_CORE]);
		clk_unprepare(mdp3_res->clocks[MDP3_CLK_VSYNC]);
		clk_unprepare(mdp3_res->clocks[MDP3_CLK_DSI]);
	} else if (mdp3_res->clk_prepare_count < 0) {
		pr_err("mdp3 clk unprepare mismatch\n");
	int rc = 0;

	if (enable) {
		rc = mdp3_clk_enable(enable, dsi_clk);
		if (rc < 0) {
			pr_err("mdp3_clk_enable failed, enable=%d, dsi_clk=%d\n",
				enable, dsi_clk);
			goto done;
		}
	mutex_unlock(&mdp3_res->res_mutex);
		mdp3_irq_register();
		mdp3_bus_bw_iommu_enable(enable, client);
	} else {
		mdp3_bus_bw_iommu_enable(enable, client);
		mdp3_irq_suspend();
		rc = mdp3_clk_enable(enable, dsi_clk);
		if (rc < 0) {
			pr_err("mdp3_clk_enable failed, enable=%d, dsi_clk=%d\n",
				enable, dsi_clk);
			goto done;
		}
	}

done:
	return rc;
}

int mdp3_get_mdp_dsi_clk(void)
@@ -646,7 +711,6 @@ int mdp3_put_mdp_dsi_clk(void)
	int rc;
	mutex_lock(&mdp3_res->res_mutex);
	rc = mdp3_clk_update(MDP3_CLK_DSI, 0);
	clk_unprepare(mdp3_res->clocks[MDP3_CLK_DSI]);
	mutex_unlock(&mdp3_res->res_mutex);
	return rc;
}
@@ -1847,6 +1911,7 @@ static int mdp3_is_display_on(struct mdss_panel_data *pdata)
static int mdp3_continuous_splash_on(struct mdss_panel_data *pdata)
{
	struct mdss_panel_info *panel_info = &pdata->panel_info;
	struct mdp3_bus_handle_map *bus_handle;
	u64 ab, ib;
	int rc;

@@ -1858,26 +1923,23 @@ static int mdp3_continuous_splash_on(struct mdss_panel_data *pdata)
	mdp3_clk_set_rate(MDP3_CLK_CORE, MDP_CORE_CLK_RATE,
			MDP3_CLIENT_DMA_P);

	rc = mdp3_clk_prepare();
	if (rc) {
		pr_err("fail to prepare clk\n");
		return rc;
	}

	rc = mdp3_clk_enable(1, 1);
	if (rc) {
		pr_err("fail to enable clk\n");
		mdp3_clk_unprepare();
		return rc;
	bus_handle = &mdp3_res->bus_handle[MDP3_BUS_HANDLE_DMA];
	if (bus_handle->handle < 1) {
		pr_err("invalid bus handle %d\n", bus_handle->handle);
		return -EINVAL;
	}

	ab = panel_info->xres * panel_info->yres * 4;
	ab *= panel_info->mipi.frame_rate;
	ib = (ab * 3) / 2;
	rc = mdp3_bus_scale_set_quota(MDP3_CLIENT_DMA_P, ab, ib);
	bus_handle->restore_ab = ab;
	bus_handle->restore_ib = ib;

	rc = mdp3_res_update(1, 1, MDP3_CLIENT_DMA_P);
	if (rc) {
		pr_err("fail to request bus bandwidth\n");
		goto splash_on_err;
		pr_err("fail to enable clk\n");
		return rc;
	}

	rc = mdp3_ppp_init();
@@ -1886,8 +1948,6 @@ static int mdp3_continuous_splash_on(struct mdss_panel_data *pdata)
		goto splash_on_err;
	}

	mdp3_irq_register();

	if (pdata->event_handler) {
		rc = pdata->event_handler(pdata, MDSS_EVENT_CONT_SPLASH_BEGIN,
					NULL);
@@ -1907,10 +1967,9 @@ static int mdp3_continuous_splash_on(struct mdss_panel_data *pdata)
	return 0;

splash_on_err:
	if (mdp3_clk_enable(0, 1))
	if (mdp3_res_update(0, 1, MDP3_CLIENT_DMA_P))
		pr_err("%s: Unable to disable mdp3 clocks\n", __func__);

	mdp3_clk_unprepare();
	return rc;
}

@@ -1930,6 +1989,12 @@ static int mdp3_panel_register_done(struct mdss_panel_data *pdata)
			rc = mdp3_continuous_splash_on(pdata);
		}
	}
	/*
	 * We want to prevent iommu from being enabled if there is
	 * continue splash screen. This would have happened in
	 * res_update in continuous_splash_on without this flag.
	 */
	mdp3_res->allow_iommu_update = true;
	return rc;
}

@@ -1944,11 +2009,9 @@ static int mdp3_debug_dump_stats(void *data, char *buf, int len)
static void mdp3_debug_enable_clock(int on)
{
	if (on) {
		mdp3_clk_prepare();
		mdp3_clk_enable(1, 0);
	} else {
		mdp3_clk_enable(0, 0);
		mdp3_clk_unprepare();
	}
}

+6 −2
Original line number Diff line number Diff line
@@ -73,6 +73,9 @@ struct mdp3_bus_handle_map {
	struct msm_bus_paths *usecases;
	struct msm_bus_scale_pdata *scale_pdata;
	int current_bus_idx;
	int ref_cnt;
	u64 restore_ab;
	u64 restore_ib;
	u32 handle;
};

@@ -133,6 +136,7 @@ struct mdp3_hw_resource {
	struct ion_client *ion_client;
	struct mdp3_iommu_domain_map *domains;
	struct mdp3_iommu_ctx_map *iommu_contexts;
	bool allow_iommu_update;
	struct ion_handle *ion_handle;
	struct mutex iommu_lock;
	struct rb_root iommu_root;
@@ -143,6 +147,7 @@ struct mdp3_hw_resource {
	spinlock_t irq_lock;
	u32 irq_ref_count[MDP3_MAX_INTR];
	u32 irq_mask;
	int irq_ref_cnt;
	struct mdp3_intr_cb callbacks[MDP3_MAX_INTR];
	u32 underrun_cnt;

@@ -182,8 +187,7 @@ void mdp3_irq_register(void);
void mdp3_irq_deregister(void);
int mdp3_clk_set_rate(int clk_type, unsigned long clk_rate, int client);
int mdp3_clk_enable(int enable, int dsi_clk);
int mdp3_clk_prepare(void);
void mdp3_clk_unprepare(void);
int mdp3_res_update(int enable, int dsi_clk, int client);
int mdp3_bus_scale_set_quota(int client, u64 ab_quota, u64 ib_quota);
int mdp3_put_img(struct mdp3_img_data *data, int client);
int mdp3_get_img(struct msmfb_data *img, struct mdp3_img_data *data,
+6 −34
Original line number Diff line number Diff line
@@ -338,7 +338,7 @@ static int mdp3_ctrl_clk_enable(struct msm_fb_data_type *mfd, int enable)
				(!enable && session->clk_on == 1)) {
		rc = panel->event_handler(panel,
			MDSS_EVENT_PANEL_CLK_CTRL, (void *)enable);
		rc |= mdp3_clk_enable(enable, 1);
		rc |= mdp3_res_update(enable, 1, MDP3_CLIENT_DMA_P);
	} else {
		pr_debug("enable = %d, clk_on=%d\n", enable, session->clk_on);
	}
@@ -374,24 +374,15 @@ static int mdp3_ctrl_res_req_clk(struct msm_fb_data_type *mfd, int status)
		mdp3_clk_set_rate(MDP3_CLK_VSYNC, MDP_VSYNC_CLK_RATE,
				MDP3_CLIENT_DMA_P);

		rc = mdp3_clk_prepare();
		if (rc) {
			pr_err("mdp3 clk prepare fail\n");
			return rc;
		}

		rc = mdp3_clk_enable(1, 1);
		rc = mdp3_res_update(1, 1, MDP3_CLIENT_DMA_P);
		if (rc) {
			pr_err("mdp3 clk enable fail\n");
			mdp3_clk_unprepare();
			return rc;
		}
	} else {
		rc = mdp3_clk_enable(0, 1);
		rc = mdp3_res_update(0, 1, MDP3_CLIENT_DMA_P);
		if (rc)
			pr_err("mdp3 clk disable fail\n");
		else
			mdp3_clk_unprepare();
	}
	return rc;
}
@@ -588,12 +579,6 @@ static int mdp3_ctrl_on(struct msm_fb_data_type *mfd)
	mdp3_ctrl_notifier_register(mdp3_session,
		&mdp3_session->mfd->mdp_sync_pt_data.notifier);

	rc = mdp3_iommu_enable(MDP3_CLIENT_DMA_P);
	if (rc) {
		pr_err("fail to attach MDP DMA SMMU\n");
		goto on_error;
	}

	/* request bus bandwidth before DSI DMA traffic */
	rc = mdp3_ctrl_res_req_bus(mfd, 1);
	if (rc) {
@@ -616,8 +601,6 @@ static int mdp3_ctrl_on(struct msm_fb_data_type *mfd)
		goto on_error;
	}

	mdp3_irq_register();

	rc = mdp3_ctrl_dma_init(mfd, mdp3_session->dma);
	if (rc) {
		pr_err("dma init failed\n");
@@ -635,7 +618,6 @@ static int mdp3_ctrl_on(struct msm_fb_data_type *mfd)
		pr_err("display interface init failed\n");
		goto on_error;
	}

	mdp3_session->clk_on = 1;

	mdp3_session->first_commit = true;
@@ -687,7 +669,7 @@ static int mdp3_ctrl_off(struct msm_fb_data_type *mfd)

	pr_debug("mdp3_ctrl_off stop clock\n");
	if (mdp3_session->clk_on) {
		rc = mdp3_clk_enable(0, 1);
		rc = mdp3_res_update(0, 1, MDP3_CLIENT_DMA_P);
		if (rc)
			pr_err("mdp clock resource release failed\n");

@@ -698,16 +680,6 @@ static int mdp3_ctrl_off(struct msm_fb_data_type *mfd)
		if (rc)
			pr_err("fail to turn off the panel\n");
	}
	mdp3_clk_unprepare();

	pr_debug("mdp3_ctrl_off release bus\n");
	rc = mdp3_ctrl_res_req_bus(mfd, 0);
	if (rc)
		pr_err("mdp bus resource release failed\n");

	rc = mdp3_iommu_disable(MDP3_CLIENT_DMA_P);
	if (rc)
		pr_err("fail to dettach MDP DMA SMMU\n");

	mdp3_ctrl_notifier_unregister(mdp3_session,
		&mdp3_session->mfd->mdp_sync_pt_data.notifier);
@@ -1317,7 +1289,7 @@ static int mdp3_histogram_start(struct mdp3_session_data *session,
		return -EBUSY;
	}

	mdp3_clk_enable(1, 0);
	mdp3_res_update(1, 0, MDP3_CLIENT_DMA_P);
	ret = session->dma->histo_op(session->dma, MDP3_DMA_HISTO_OP_RESET);
	if (ret) {
		pr_err("mdp3_histogram_start reset error\n");
@@ -1343,7 +1315,7 @@ static int mdp3_histogram_start(struct mdp3_session_data *session,
	session->histo_status = 1;

histogram_start_err:
	mdp3_clk_enable(0, 0);
	mdp3_res_update(0, 0, MDP3_CLIENT_DMA_P);
	mutex_unlock(&session->histo_lock);
	return ret;
}
+2 −13
Original line number Diff line number Diff line
@@ -386,14 +386,14 @@ int mdp3_ppp_turnon(struct msm_fb_data_type *mfd, int on_off)
			ab = req_bw;
	}
	mdp3_clk_set_rate(MDP3_CLK_CORE, rate, MDP3_CLIENT_PPP);
	rc = mdp3_clk_enable(on_off, 0);
	rc = mdp3_res_update(on_off, 0, MDP3_CLIENT_PPP);
	if (rc < 0) {
		pr_err("%s: mdp3_clk_enable failed\n", __func__);
		return rc;
	}
	rc = mdp3_bus_scale_set_quota(MDP3_CLIENT_PPP, ab, ib);
	if (rc < 0) {
		mdp3_clk_enable(!on_off, 0);
		mdp3_res_update(!on_off, 0, MDP3_CLIENT_PPP);
		pr_err("%s: scale_set_quota failed\n", __func__);
		return rc;
	}
@@ -1039,14 +1039,10 @@ void mdp3_free_fw_timer_func(unsigned long arg)
static void mdp3_free_bw_wq_handler(struct work_struct *work)
{
	struct msm_fb_data_type *mfd = ppp_stat->mfd;
	int rc;

	mutex_lock(&ppp_stat->config_ppp_mutex);
	if (ppp_stat->bw_on) {
		mdp3_ppp_turnon(mfd, 0);
		rc = mdp3_iommu_disable(MDP3_CLIENT_PPP);
		if (rc < 0)
			WARN(1, "Unable to disable ppp iommu\n");
	}
	mutex_unlock(&ppp_stat->config_ppp_mutex);
}
@@ -1065,16 +1061,9 @@ static void mdp3_ppp_blit_wq_handler(struct work_struct *work)
	}

	if (!ppp_stat->bw_on) {
		rc = mdp3_iommu_enable(MDP3_CLIENT_PPP);
		if (rc < 0) {
			mutex_unlock(&ppp_stat->config_ppp_mutex);
			pr_err("%s: mdp3_iommu_enable failed\n", __func__);
			return;
		}
		ppp_stat->bw_optimal = mdp3_optimal_bw(req->count);
		mdp3_ppp_turnon(mfd, 1);
		if (rc < 0) {
			mdp3_iommu_disable(MDP3_CLIENT_PPP);
			mutex_unlock(&ppp_stat->config_ppp_mutex);
			pr_err("%s: Enable ppp resources failed\n", __func__);
			return;