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

Commit 297e0cf4 authored by Xiaoming Zhou's avatar Xiaoming Zhou Committed by Terence Hampson
Browse files

mdss: mdp3: request and release clocks for every mdp operation



In the command mode panel, all the clocks can be voted off if
there is no display update.  To support this feature, every
operation which requires h/w access will be guarded with clock
vote on and off.

Change-Id: If56a656b9965a6044c38de5aa85969256d581121
Signed-off-by: default avatarXiaoming Zhou <zhoux@codeaurora.org>
parent 61a09d4a
Loading
Loading
Loading
Loading
+91 −17
Original line number Diff line number Diff line
@@ -184,11 +184,11 @@ static irqreturn_t mdp3_irq_handler(int irq, void *ptr)
	u32 mdp_interrupt = 0;

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

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

	mdp_interrupt = MDP3_REG_READ(MDP3_REG_INTR_STATUS);
	MDP3_REG_WRITE(MDP3_REG_INTR_CLEAR, mdp_interrupt);
@@ -202,6 +202,10 @@ static irqreturn_t mdp3_irq_handler(int irq, void *ptr)
		mdp_interrupt = mdp_interrupt >> 1;
		i++;
	}

	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,8 +285,6 @@ void mdp3_irq_deregister(void)
	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_REG_WRITE(MDP3_REG_INTR_CLEAR, 0xfffffff);
	disable_irq_nosync(mdp3_res->irq);
	spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
}
@@ -415,10 +417,10 @@ 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_enable(clk);
		ret = clk_enable(clk);
	} else if (count == 0) {
		pr_debug("clk=%d disable\n", clk_idx);
		clk_disable_unprepare(clk);
		clk_disable(clk);
		ret = 0;
	} else if (count < 0) {
		pr_err("clk=%d count=%d\n", clk_idx, count);
@@ -554,7 +556,7 @@ static void mdp3_clk_remove(void)
		clk_put(mdp3_res->clocks[MDP3_CLK_DSI]);
}

int mdp3_clk_enable(int enable)
int mdp3_clk_enable(int enable, int dsi_clk)
{
	int rc;

@@ -564,11 +566,62 @@ int mdp3_clk_enable(int enable)
	rc = mdp3_clk_update(MDP3_CLK_AHB, enable);
	rc |= mdp3_clk_update(MDP3_CLK_CORE, enable);
	rc |= mdp3_clk_update(MDP3_CLK_VSYNC, enable);
	if (dsi_clk)
		rc |= mdp3_clk_update(MDP3_CLK_DSI, enable);
	mutex_unlock(&mdp3_res->res_mutex);
	return rc;
}

int mdp3_clk_prepare(void)
{
	int rc = 0;

	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;
	}
	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--;
	mutex_unlock(&mdp3_res->res_mutex);
	return rc;
}

void mdp3_clk_unprepare(void)
{
	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");
	}
	mutex_unlock(&mdp3_res->res_mutex);
}

static int mdp3_irq_setup(void)
{
	int ret;
@@ -1514,8 +1567,17 @@ int mdp3_iommu_is_attached(int client)
static int mdp3_init(struct msm_fb_data_type *mfd)
{
	int rc;

	rc = mdp3_ctrl_init(mfd);
	rc |= mdp3_ppp_res_init(mfd);
	if (rc) {
		pr_err("mdp3 ctl init fail\n");
		return rc;
	}

	rc = mdp3_ppp_res_init(mfd);
	if (rc)
		pr_err("mdp3 ppp res init fail\n");

	return rc;
}

@@ -1743,9 +1805,16 @@ static int mdp3_continuous_splash_on(struct mdss_panel_data *pdata)

	pr_debug("mdp3__continuous_splash_on\n");

	rc = mdp3_clk_enable(1);
	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;
	}

@@ -1782,8 +1851,10 @@ static int mdp3_continuous_splash_on(struct mdss_panel_data *pdata)
	return 0;

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

	mdp3_clk_unprepare();
	return rc;
}

@@ -1816,10 +1887,13 @@ static int mdp3_debug_dump_stats(void *data, char *buf, int len)

static void mdp3_debug_enable_clock(int on)
{
	if (on)
		mdp3_clk_enable(1);
	else
		mdp3_clk_enable(0);
	if (on) {
		mdp3_clk_prepare();
		mdp3_clk_enable(1, 0);
	} else {
		mdp3_clk_enable(0, 0);
		mdp3_clk_unprepare();
	}
}

static int mdp3_debug_init(struct platform_device *pdev)
+5 −1
Original line number Diff line number Diff line
@@ -150,6 +150,8 @@ struct mdp3_hw_resource {
	u32 splash_mem_addr;
	u32 splash_mem_size;
	struct mdss_panel_cfg pan_cfg;

	int clk_prepare_count;
};

struct mdp3_img_data {
@@ -173,7 +175,9 @@ int mdp3_set_intr_callback(u32 type, struct mdp3_intr_cb *cb);
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 mdp3_clk_enable(int enable, int dsi_clk);
int mdp3_clk_prepare(void);
void mdp3_clk_unprepare(void);
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,
+35 −7
Original line number Diff line number Diff line
@@ -118,7 +118,9 @@ static int mdp3_ctrl_vsync_enable(struct msm_fb_data_type *mfd, int enable)
	}

	mutex_lock(&mdp3_session->lock);
	mdp3_clk_enable(1, 0);
	mdp3_session->dma->vsync_enable(mdp3_session->dma, arg);
	mdp3_clk_enable(0, 0);
	if (enable && mdp3_session->status == 1 && !mdp3_session->intf->active)
		mod_timer(&mdp3_session->vsync_timer,
			jiffies + msecs_to_jiffies(mdp3_session->vsync_period));
@@ -236,12 +238,24 @@ 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_enable(true);
		if (rc)
		rc = mdp3_clk_prepare();
		if (rc) {
			pr_err("mdp3 clk prepare fail\n");
			return rc;
		}

		rc = mdp3_clk_enable(1, 1);
		if (rc) {
			pr_err("mdp3 clk enable fail\n");
			mdp3_clk_unprepare();
			return rc;
		}
	} else {
		rc = mdp3_clk_enable(false);
		rc = mdp3_clk_enable(0, 1);
		if (rc)
			pr_err("mdp3 clk disable fail\n");
		else
			mdp3_clk_unprepare();
	}
	return rc;
}
@@ -514,19 +528,21 @@ static int mdp3_ctrl_off(struct msm_fb_data_type *mfd)
		goto off_error;
	}

	mdp3_clk_enable(1, 0);

	mdp3_histogram_stop(mdp3_session, MDP_BLOCK_DMA_P);

	rc = mdp3_session->dma->stop(mdp3_session->dma, mdp3_session->intf);
	if (rc)
		pr_debug("fail to stop the MDP3 dma\n");

	mdp3_clk_enable(0, 0);

	if (panel->event_handler)
		rc = panel->event_handler(panel, MDSS_EVENT_PANEL_OFF, NULL);
	if (rc)
		pr_err("fail to turn off the panel\n");



	mdp3_irq_deregister();

	pr_debug("mdp3_ctrl_off stop clock\n");
@@ -843,9 +859,11 @@ static int mdp3_ctrl_display_commit_kickoff(struct msm_fb_data_type *mfd,

	data = mdp3_bufq_pop(&mdp3_session->bufq_in);
	if (data) {
		mdp3_clk_enable(1, 0);
		mdp3_session->dma->update(mdp3_session->dma,
			(void *)(int)data->addr,
			mdp3_session->intf);
		mdp3_clk_enable(0, 0);
		mdp3_bufq_push(&mdp3_session->bufq_out, data);
	}

@@ -911,6 +929,7 @@ static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd)
		goto pan_error;
	}

	mdp3_clk_enable(1, 0);
	if (mfd->fbi->screen_base) {
		mdp3_session->dma->update(mdp3_session->dma,
				(void *)(int)(mfd->iova + offset),
@@ -919,6 +938,7 @@ static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd)
		pr_debug("mdp3_ctrl_pan_display no memory, stop interface");
		mdp3_session->dma->stop(mdp3_session->dma, mdp3_session->intf);
	}
	mdp3_clk_enable(0, 0);

	if (mdp3_session->first_commit) {
		/*wait for one frame time to ensure frame is sent to panel*/
@@ -1033,10 +1053,11 @@ static int mdp3_histogram_start(struct mdp3_session_data *session,

	if (session->histo_status) {
		pr_err("mdp3_histogram_start already started\n");
		ret = -EBUSY;
		goto histogram_start_err;
		mutex_unlock(&session->histo_lock);
		return -EBUSY;
	}

	mdp3_clk_enable(1, 0);
	ret = session->dma->histo_op(session->dma, MDP3_DMA_HISTO_OP_RESET);
	if (ret) {
		pr_err("mdp3_histogram_start reset error\n");
@@ -1062,6 +1083,8 @@ static int mdp3_histogram_start(struct mdp3_session_data *session,
	session->histo_status = 1;

histogram_start_err:
	if (ret)
		mdp3_clk_enable(0, 0);
	mutex_unlock(&session->histo_lock);
	return ret;
}
@@ -1085,6 +1108,7 @@ static int mdp3_histogram_stop(struct mdp3_session_data *session,
	}

	ret = session->dma->histo_op(session->dma, MDP3_DMA_HISTO_OP_CANCEL);
	mdp3_clk_enable(0, 0);
	if (ret)
		pr_err("mdp3_histogram_stop error\n");

@@ -1198,7 +1222,9 @@ static int mdp3_csc_config(struct mdp3_session_data *session,
	ccs.post_lv = data->csc_data.csc_post_lv;

	mutex_lock(&session->lock);
	mdp3_clk_enable(1, 0);
	ret = session->dma->config_ccs(session->dma, &config, &ccs);
	mdp3_clk_enable(0, 0);
	mutex_unlock(&session->lock);
	return ret;
}
@@ -1340,8 +1366,10 @@ static int mdp3_ctrl_lut_update(struct msm_fb_data_type *mfd,
		return -EPERM;
	}

	mdp3_clk_enable(1, 0);
	rc = mdp3_session->dma->config_lut(mdp3_session->dma, &lut_config,
					&lut);
	mdp3_clk_enable(0, 0);
	if (rc)
		pr_err("mdp3_ctrl_lut_update failed\n");

+3 −0
Original line number Diff line number Diff line
@@ -828,6 +828,9 @@ static int mdp3_dma_stop(struct mdp3_dma *dma, struct mdp3_intf *intf)
					MDP3_DMA_CALLBACK_TYPE_DMA_DONE);
	mdp3_irq_disable(MDP3_INTR_LCDC_UNDERFLOW);

	MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, 0);
	MDP3_REG_WRITE(MDP3_REG_INTR_CLEAR, 0xfffffff);

	init_completion(&dma->dma_comp);
	dma->vsync_client.handler = NULL;
	return ret;
+2 −2
Original line number Diff line number Diff line
@@ -370,14 +370,14 @@ int mdp3_ppp_turnon(struct msm_fb_data_type *mfd, int on_off)
		ib = (ab * 3) / 2;
	}
	mdp3_clk_set_rate(MDP3_CLK_CORE, rate, MDP3_CLIENT_PPP);
	rc = mdp3_clk_enable(on_off);
	rc = mdp3_clk_enable(on_off, 0);
	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);
		mdp3_clk_enable(!on_off, 0);
		pr_err("%s: scale_set_quota failed\n", __func__);
		return rc;
	}