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

Commit 8bea4e33 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: dsi-1 as master clock controller at split display case"

parents 4812b01f a7d8cd7c
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -395,7 +395,7 @@ int mdss_dsi_on(struct mdss_panel_data *pdata)
			return ret;
		}
	}
	ret = mdss_dsi_enable_bus_clocks(ctrl_pdata);
	ret = mdss_dsi_bus_clk_start(ctrl_pdata);
	if (ret) {
		pr_err("%s: failed to enable bus clocks. rc=%d\n", __func__,
			ret);
@@ -412,7 +412,7 @@ int mdss_dsi_on(struct mdss_panel_data *pdata)
	pdata->panel_info.panel_power_on = 1;
	mdss_dsi_phy_sw_reset((ctrl_pdata->ctrl_base));
	mdss_dsi_phy_init(pdata);
	mdss_dsi_disable_bus_clocks(ctrl_pdata);
	mdss_dsi_bus_clk_stop(ctrl_pdata);

	mdss_dsi_clk_ctrl(ctrl_pdata, 1);

+12 −1
Original line number Diff line number Diff line
@@ -222,6 +222,8 @@ enum {
#define DSI_EV_MDP_FIFO_UNDERFLOW	0x0002
#define DSI_EV_MDP_BUSY_RELEASE		0x80000000

#define DSI_FLAG_CLOCK_MASTER		0x80000000

struct mdss_dsi_ctrl_pdata {
	int ndx;	/* panel_num */
	int (*on) (struct mdss_panel_data *pdata);
@@ -233,6 +235,8 @@ struct mdss_dsi_ctrl_pdata {
	unsigned char *ctrl_base;
	int reg_size;
	u32 clk_cnt;
	int clk_cnt_sub;
	u32 flags;
	struct clk *mdp_core_clk;
	struct clk *ahb_clk;
	struct clk *axi_clk;
@@ -305,13 +309,20 @@ void mdp4_dsi_cmd_trigger(void);
void mdss_dsi_cmd_mdp_start(struct mdss_dsi_ctrl_pdata *ctrl);
void mdss_dsi_cmd_bta_sw_trigger(struct mdss_panel_data *pdata);
void mdss_dsi_ack_err_status(struct mdss_dsi_ctrl_pdata *ctrl);
int mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable);
void mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable);
int mdss_dsi_link_clk_start(struct mdss_dsi_ctrl_pdata *ctrl);
void mdss_dsi_link_clk_stop(struct mdss_dsi_ctrl_pdata *ctrl);
int mdss_dsi_bus_clk_start(struct mdss_dsi_ctrl_pdata *ctrl);
void mdss_dsi_bus_clk_stop(struct mdss_dsi_ctrl_pdata *ctrl);
void mdss_dsi_clk_req(struct mdss_dsi_ctrl_pdata *ctrl,
				int enable);
void mdss_dsi_controller_cfg(int enable,
				struct mdss_panel_data *pdata);
void mdss_dsi_sw_reset(struct mdss_panel_data *pdata);

struct mdss_dsi_ctrl_pdata *mdss_dsi_ctrl_slave(
				struct mdss_dsi_ctrl_pdata *ctrl);

irqreturn_t mdss_dsi_isr(int irq, void *ptr);
void mdss_dsi_irq_handler_config(struct mdss_dsi_ctrl_pdata *ctrl_pdata);

+22 −2
Original line number Diff line number Diff line
@@ -92,6 +92,10 @@ void mdss_dsi_ctrl_init(struct mdss_dsi_ctrl_pdata *ctrl)

	ctrl_list[ctrl->ndx] = ctrl;	/* keep it */

	if (ctrl->shared_pdata.broadcast_enable)
		if (ctrl->ndx == DSI_CTRL_1)
			ctrl->flags |= DSI_FLAG_CLOCK_MASTER;

	if (mdss_register_irq(ctrl->dsi_hw))
		pr_err("%s: mdss_register_irq failed.\n", __func__);

@@ -117,6 +121,22 @@ void mdss_dsi_ctrl_init(struct mdss_dsi_ctrl_pdata *ctrl)
	}
}

struct mdss_dsi_ctrl_pdata *mdss_dsi_ctrl_slave(
				struct mdss_dsi_ctrl_pdata *ctrl)
{
	int ndx;
	struct mdss_dsi_ctrl_pdata *sctrl = NULL;

	/* only two controllers */
	ndx = ctrl->ndx;
	ndx += 1;
	ndx %= DSI_CTRL_MAX;
	sctrl = ctrl_list[ndx];

	return sctrl;

}

void mdss_dsi_clk_req(struct mdss_dsi_ctrl_pdata *ctrl, int enable)
{
	if (enable == 0) {
@@ -1463,10 +1483,10 @@ irqreturn_t mdss_dsi_isr(int irq, void *ptr)
			MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0110, isr0);
		}

	pr_debug("%s: isr=%x", __func__, isr);
	pr_debug("%s: ndx=%d isr=%x\n", __func__, ctrl->ndx, isr);

	if (isr & DSI_INTR_ERROR) {
		pr_err("%s: isr=%x %x", __func__, isr, (int)DSI_INTR_ERROR);
		pr_err("%s: ndx=%d isr=%x\n", __func__, ctrl->ndx, isr);
		mdss_dsi_error(ctrl);
	}

+115 −104
Original line number Diff line number Diff line
/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -257,10 +257,12 @@ int mdss_dsi_clk_div_config(struct mdss_panel_info *panel_info,
	return 0;
}

int mdss_dsi_enable_bus_clocks(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
int mdss_dsi_bus_clk_start(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
{
	int rc = 0;

	pr_debug("%s: ndx=%d\n", __func__, ctrl_pdata->ndx);

	rc = clk_prepare_enable(ctrl_pdata->mdp_core_clk);
	if (rc) {
		pr_err("%s: failed to enable mdp_core_clock. rc=%d\n",
@@ -287,29 +289,14 @@ error:
	return rc;
}

void mdss_dsi_disable_bus_clocks(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
void mdss_dsi_bus_clk_stop(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
{
	if (ctrl_pdata->shared_pdata.broadcast_enable) {
		if (ctrl_pdata->panel_data.panel_info.pdest == DISPLAY_1) {
			pr_debug("%s: Broadcast mode enabled.\n",
				 __func__);
			return;
		} else if (left_ctrl &&
				(ctrl_pdata->panel_data.panel_info.pdest
							== DISPLAY_2)) {
			pr_debug("%s: disable_unprepare left ctrl bus clks\n",
							__func__);
			clk_disable_unprepare(left_ctrl->axi_clk);
			clk_disable_unprepare(left_ctrl->ahb_clk);
			clk_disable_unprepare(left_ctrl->mdp_core_clk);
		}
	}
	clk_disable_unprepare(ctrl_pdata->axi_clk);
	clk_disable_unprepare(ctrl_pdata->ahb_clk);
	clk_disable_unprepare(ctrl_pdata->mdp_core_clk);
}

static int mdss_dsi_clk_prepare(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
static int mdss_dsi_link_clk_prepare(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
{
	int rc = 0;

@@ -341,34 +328,19 @@ esc_clk_err:
	return rc;
}

static void mdss_dsi_clk_unprepare(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
static void mdss_dsi_link_clk_unprepare(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
{
	if (!ctrl_pdata) {
		pr_err("%s: Invalid input data\n", __func__);
		return;
	}

	if (ctrl_pdata->shared_pdata.broadcast_enable) {
		if (ctrl_pdata->panel_data.panel_info.pdest == DISPLAY_1) {
			pr_debug("%s: Broadcast mode enabled.\n",
				 __func__);
			return;
		} else if (left_ctrl &&
				(ctrl_pdata->panel_data.panel_info.pdest
							== DISPLAY_2)) {
			pr_debug("%s: unprepare left ctrl clocks\n", __func__);
			clk_unprepare(left_ctrl->pixel_clk);
			clk_unprepare(left_ctrl->byte_clk);
			clk_unprepare(left_ctrl->esc_clk);
		}
	}

	clk_unprepare(ctrl_pdata->pixel_clk);
	clk_unprepare(ctrl_pdata->byte_clk);
	clk_unprepare(ctrl_pdata->esc_clk);
}

static int mdss_dsi_clk_set_rate(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
static int mdss_dsi_link_clk_set_rate(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
{
	u32 esc_clk_rate = 19200000;
	int rc = 0;
@@ -409,7 +381,7 @@ error:
	return rc;
}

static int mdss_dsi_clk_enable(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
static int mdss_dsi_link_clk_enable(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
{
	int rc = 0;

@@ -418,6 +390,8 @@ static int mdss_dsi_clk_enable(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
		return -EINVAL;
	}

	pr_debug("%s: ndx=%d\n", __func__, ctrl_pdata->ndx);

	if (ctrl_pdata->mdss_dsi_clk_on) {
		pr_info("%s: mdss_dsi_clks already ON\n", __func__);
		return 0;
@@ -453,34 +427,20 @@ esc_clk_err:
	return rc;
}

static void mdss_dsi_clk_disable(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
static void mdss_dsi_link_clk_disable(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
{
	if (!ctrl_pdata) {
		pr_err("%s: Invalid input data\n", __func__);
		return;
	}

	pr_debug("%s: ndx=%d\n", __func__, ctrl_pdata->ndx);

	if (ctrl_pdata->mdss_dsi_clk_on == 0) {
		pr_info("%s: mdss_dsi_clks already OFF\n", __func__);
		return;
	}

	if (ctrl_pdata->shared_pdata.broadcast_enable) {
		if (ctrl_pdata->panel_data.panel_info.pdest == DISPLAY_1) {
			pr_debug("%s: Broadcast mode enabled.\n",
				 __func__);
			return;
		} else if (left_ctrl &&
				(ctrl_pdata->panel_data.panel_info.pdest
							== DISPLAY_2)) {
			pr_debug("%s: disabled left ctrl clocks\n", __func__);
			clk_disable(left_ctrl->pixel_clk);
			clk_disable(left_ctrl->byte_clk);
			clk_disable(left_ctrl->esc_clk);
			left_ctrl->mdss_dsi_clk_on = 0;
		}
	}

	clk_disable(ctrl_pdata->esc_clk);
	clk_disable(ctrl_pdata->pixel_clk);
	clk_disable(ctrl_pdata->byte_clk);
@@ -488,62 +448,110 @@ static void mdss_dsi_clk_disable(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
	ctrl_pdata->mdss_dsi_clk_on = 0;
}

int mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable)
int mdss_dsi_link_clk_start(struct mdss_dsi_ctrl_pdata *ctrl)
{
	int rc = 0;

	mutex_lock(&ctrl->mutex);
	if (enable) {
		if (ctrl->clk_cnt == 0) {
			rc = mdss_dsi_enable_bus_clocks(ctrl);
			if (rc) {
				pr_err("%s: failed to enable bus clks. rc=%d\n",
					__func__, rc);
				goto error;
			}

			rc = mdss_dsi_clk_set_rate(ctrl);
	rc = mdss_dsi_link_clk_set_rate(ctrl);
	if (rc) {
		pr_err("%s: failed to set clk rates. rc=%d\n",
			__func__, rc);
				mdss_dsi_disable_bus_clocks(ctrl);
		goto error;
	}

			rc = mdss_dsi_clk_prepare(ctrl);
	rc = mdss_dsi_link_clk_prepare(ctrl);
	if (rc) {
		pr_err("%s: failed to prepare clks. rc=%d\n",
			__func__, rc);
				mdss_dsi_disable_bus_clocks(ctrl);
		goto error;
	}

			rc = mdss_dsi_clk_enable(ctrl);
	rc = mdss_dsi_link_clk_enable(ctrl);
	if (rc) {
		pr_err("%s: failed to enable clks. rc=%d\n",
			__func__, rc);
				mdss_dsi_clk_unprepare(ctrl);
				mdss_dsi_disable_bus_clocks(ctrl);
		mdss_dsi_link_clk_unprepare(ctrl);
		goto error;
	}

error:
	return rc;
}

void mdss_dsi_link_clk_stop(struct mdss_dsi_ctrl_pdata *ctrl)
{
	mdss_dsi_link_clk_disable(ctrl);
	mdss_dsi_link_clk_unprepare(ctrl);
}

static void mdss_dsi_clk_ctrl_sub(struct mdss_dsi_ctrl_pdata *ctrl, int enable)
{
	int changed = 0;

	if (enable) {
		if (ctrl->clk_cnt_sub == 0)
			changed++;
		ctrl->clk_cnt_sub++;
	} else {
		if (ctrl->clk_cnt_sub) {
			ctrl->clk_cnt_sub--;
			if (ctrl->clk_cnt_sub == 0)
				changed++;
		} else {
			pr_debug("%s: Can not be turned off\n", __func__);
		}
	}

	pr_debug("%s: ndx=%d clk_cnt_sub=%d changed=%d enable=%d\n",
		__func__, ctrl->ndx, ctrl->clk_cnt_sub, changed, enable);
	if (changed) {
		if (enable) {
			if (mdss_dsi_bus_clk_start(ctrl) == 0)
				mdss_dsi_link_clk_start(ctrl);
		} else {
			mdss_dsi_link_clk_stop(ctrl);
			mdss_dsi_bus_clk_stop(ctrl);
		}
	}
}

static DEFINE_MUTEX(dsi_clk_lock); /* per system */

void mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable)
{
	int changed = 0;
	struct mdss_dsi_ctrl_pdata *sctrl = NULL;

	mutex_lock(&dsi_clk_lock);
	if (enable) {
		if (ctrl->clk_cnt == 0)
			changed++;
		ctrl->clk_cnt++;
	} else {
		if (ctrl->clk_cnt) {
			ctrl->clk_cnt--;
			if (ctrl->clk_cnt == 0) {
				mdss_dsi_clk_disable(ctrl);
				mdss_dsi_clk_unprepare(ctrl);
				mdss_dsi_disable_bus_clocks(ctrl);
			}
			if (ctrl->clk_cnt == 0)
				changed++;
		} else {
			pr_debug("%s: Can not be turned off\n", __func__);
		}
	}
	pr_debug("%s: ctrl ndx=%d enabled=%d clk_cnt=%d\n",
			__func__, ctrl->ndx, enable, ctrl->clk_cnt);

error:
	mutex_unlock(&ctrl->mutex);
	return rc;
	pr_debug("%s: ndx=%d clk_cnt=%d changed=%d enable=%d\n",
		__func__, ctrl->ndx, ctrl->clk_cnt, changed, enable);
	if (ctrl->flags & DSI_FLAG_CLOCK_MASTER)
		sctrl = mdss_dsi_ctrl_slave(ctrl);

	if (changed) {
		if (enable && sctrl)
			mdss_dsi_clk_ctrl_sub(sctrl, enable);

		mdss_dsi_clk_ctrl_sub(ctrl, enable);

		if (!enable && sctrl)
			mdss_dsi_clk_ctrl_sub(sctrl, enable);
	}
	mutex_unlock(&dsi_clk_lock);
}

void mdss_dsi_phy_sw_reset(unsigned char *ctrl_base)
@@ -566,16 +574,19 @@ void mdss_dsi_phy_disable(struct mdss_dsi_ctrl_pdata *ctrl)
	}

	if (left_ctrl &&
		(ctrl->panel_data.panel_info.pdest
					== DISPLAY_1))
			(ctrl->panel_data.panel_info.pdest == DISPLAY_1))
		return;

	if (left_ctrl &&
			(ctrl->panel_data.panel_info.pdest
					== DISPLAY_2)) {
		MIPI_OUTP(left_ctrl->ctrl_base + 0x0470, 0x000);
		MIPI_OUTP(left_ctrl->ctrl_base + 0x0598, 0x000);
			 ==
			 DISPLAY_2)) {
		MIPI_OUTP(left_ctrl->ctrl_base + 0x0470,
				0x000);
		MIPI_OUTP(left_ctrl->ctrl_base + 0x0598,
				0x000);
	}

	MIPI_OUTP(ctrl->ctrl_base + 0x0470, 0x000);
	MIPI_OUTP(ctrl->ctrl_base + 0x0598, 0x000);