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)
				changed++;
		} else {
			pr_debug("%s: Can not be turned off\n", __func__);
		}
	}

	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);
}
int mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl,
	u8 clk_type, int enable)
{
	int rc = 0;
	int link_changed = 0, bus_changed = 0;
	int m_link_changed = 0, m_bus_changed = 0;
	struct mdss_dsi_ctrl_pdata *mctrl = NULL;

	if (!ctrl) {
		pr_err("%s: Invalid arg\n", __func__);
		return -EINVAL;
	}

	/*
	 * In sync_wait_broadcast mode, we need to enable clocks
	 * for the other controller as well when enabling clocks
	 * for the trigger controller.
	 *
	 * If sync wait_broadcase mode is not enabled, but if split display
	 * mode is enabled where both DSI controller's branch clocks are
	 * sourced out of a single PLL, then we need to ensure that the
	 * controller associated with that PLL also has it's clocks turned
	 * on. This is required to make sure that if that controller's PLL/PHY
	 * are clamped then they can be removed.
	 */
	if (mdss_dsi_sync_wait_trigger(ctrl)) {
		mctrl = mdss_dsi_get_other_ctrl(ctrl);
		if (!mctrl)
			pr_warn("%s: Unable to get other control\n", __func__);
	} else if (mdss_dsi_is_ctrl_clk_slave(ctrl)) {
		mctrl = mdss_dsi_get_ctrl_clk_master();
		if (!mctrl)
			pr_warn("%s: Unable to get clk master control\n",
				__func__);
	}

	pr_debug("%s++: ndx=%d clk_type=%d bus_clk_cnt=%d link_clk_cnt=%d\n",
		__func__, ctrl->ndx, clk_type, ctrl->bus_clk_cnt,
		ctrl->link_clk_cnt);
	pr_debug("%s++: mctrl=%s m_bus_clk_cnt=%d m_link_clk_cnt=%d, enable=%d\n",
		__func__, mctrl ? "yes" : "no", mctrl ? mctrl->bus_clk_cnt : -1,
		mctrl ? mctrl->link_clk_cnt : -1, enable);

	mutex_lock(&dsi_clk_lock);

	if (clk_type & DSI_BUS_CLKS) {
		bus_changed = __mdss_dsi_update_clk_cnt(&ctrl->bus_clk_cnt,
			enable);
		if (bus_changed && mctrl)
			m_bus_changed = __mdss_dsi_update_clk_cnt(
				&mctrl->bus_clk_cnt, enable);
	}

	if (clk_type & DSI_LINK_CLKS) {
		link_changed = __mdss_dsi_update_clk_cnt(&ctrl->link_clk_cnt,
			enable);
		if (link_changed && mctrl)
			m_link_changed = __mdss_dsi_update_clk_cnt(
				&mctrl->link_clk_cnt, enable);
	}

	if (!link_changed && !bus_changed)
		goto no_error; /* clk cnts updated, nothing else needed */

	/*
	 * If updating link clock, need to make sure that the bus
	 * clocks are enabled
	 */
	if (link_changed && (!bus_changed && !ctrl->bus_clk_cnt)) {
		pr_err("%s: Trying to enable link clks w/o enabling bus clks for ctrl%d",
			__func__, ctrl->ndx);
		goto error_mctrl_bus_start;
	}

	if (m_link_changed && (!m_bus_changed && !mctrl->bus_clk_cnt)) {
		pr_err("%s: Trying to enable link clks w/o enabling bus clks for ctrl%d",
			__func__, ctrl->ndx);
		goto error_mctrl_bus_start;
	}

	if (enable && m_bus_changed) {
		rc = mdss_dsi_clk_ctrl_sub(mctrl, DSI_BUS_CLKS, 1);
		if (rc) {
			pr_err("Failed to start mctrl bus clocks rc=%d\n", rc);
			goto error_mctrl_bus_start;
		}
	}
	if (enable && bus_changed) {
		rc = mdss_dsi_clk_ctrl_sub(ctrl, DSI_BUS_CLKS, 1);
		if (rc) {
			pr_err("Failed to start ctrl bus clocks rc=%d\n", rc);
			goto error_ctrl_bus_start;
		}
	}

	if (m_link_changed) {
		rc = mdss_dsi_clk_ctrl_sub(mctrl, DSI_LINK_CLKS, enable);
		if (rc) {
			pr_err("Failed to %s mctrl clocks. rc=%d\n",
			(enable ? "start" : "stop"), rc);
			goto error_mctrl_link_change;
		}
	}
	if (link_changed) {
		rc = mdss_dsi_clk_ctrl_sub(ctrl, DSI_LINK_CLKS, enable);
		if (rc) {
			pr_err("Failed to %s ctrl clocks. rc=%d\n",
			(enable ? "start" : "stop"), rc);
			goto error_ctrl_link_change;
		}
	}

	if (!enable && m_bus_changed) {
		rc = mdss_dsi_clk_ctrl_sub(mctrl, DSI_BUS_CLKS, 0);
		if (rc) {
			pr_err("Failed to stop mctrl bus clocks rc=%d\n", rc);
			goto error_mctrl_bus_stop;
		}
	}
	if (!enable && bus_changed) {
		rc = mdss_dsi_clk_ctrl_sub(ctrl, DSI_BUS_CLKS, 0);
		if (rc) {
			pr_err("Failed to stop ctrl bus clocks\n rc=%d", rc);
			goto error_ctrl_bus_stop;
		}
	}

	goto no_error;

error_ctrl_bus_stop:
	if (m_bus_changed)
		mdss_dsi_clk_ctrl_sub(mctrl, DSI_BUS_CLKS, 1);
error_mctrl_bus_stop:
	if (link_changed)
		mdss_dsi_clk_ctrl_sub(ctrl, DSI_LINK_CLKS, enable ? 0 : 1);
error_ctrl_link_change:
	if (m_link_changed)
		mdss_dsi_clk_ctrl_sub(mctrl, DSI_LINK_CLKS, enable ? 0 : 1);
error_mctrl_link_change:
	if (bus_changed && enable)
		mdss_dsi_clk_ctrl_sub(ctrl, DSI_BUS_CLKS, 0);
error_ctrl_bus_start:
	if (m_bus_changed && enable)
		mdss_dsi_clk_ctrl_sub(mctrl, DSI_BUS_CLKS, 0);
error_mctrl_bus_start:
	if (clk_type & DSI_BUS_CLKS) {
		if (mctrl)
			__mdss_dsi_update_clk_cnt(&mctrl->bus_clk_cnt,
				enable ? 0 : 1);
		__mdss_dsi_update_clk_cnt(&ctrl->bus_clk_cnt, enable ? 0 : 1);
	}
	if (clk_type & DSI_LINK_CLKS) {
		if (mctrl)
			__mdss_dsi_update_clk_cnt(&mctrl->link_clk_cnt,
				enable ? 0 : 1);
		__mdss_dsi_update_clk_cnt(&ctrl->link_clk_cnt, enable ? 0 : 1);
	}

no_error:
	mutex_unlock(&dsi_clk_lock);
	pr_debug("%s--: ndx=%d clk_type=%d bus_clk_cnt=%d link_clk_cnt=%d changed=%d\n",
		__func__, ctrl->ndx, clk_type, ctrl->bus_clk_cnt,
		ctrl->link_clk_cnt, link_changed && bus_changed);
	pr_debug("%s--: mctrl=%s m_bus_clk_cnt=%d m_link_clk_cnt=%d, m_changed=%d, enable=%d\n",
		__func__, mctrl ? "yes" : "no", mctrl ? mctrl->bus_clk_cnt : -1,
		mctrl ? mctrl->link_clk_cnt : -1,
		m_link_changed && m_bus_changed, enable);

	return rc;
}
int mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl,
	u8 clk_type, int enable)
{
	int rc = 0;
	int link_changed = 0, bus_changed = 0;
	int m_link_changed = 0, m_bus_changed = 0;
	struct mdss_dsi_ctrl_pdata *mctrl = NULL;

	if (!ctrl) {
		pr_err("%s: Invalid arg\n", __func__);
		return -EINVAL;
	}

	/*
	 * In broadcast mode, we need to enable clocks for the
	 * master controller as well when enabling clocks for the
	 * slave controller
	 */
	if (mdss_dsi_is_slave_ctrl(ctrl)) {
		mctrl = mdss_dsi_get_master_ctrl();
		if (!mctrl)
			pr_warn("%s: Unable to get master control\n", __func__);
	}

	pr_debug("%s++: ndx=%d clk_type=%d bus_clk_cnt=%d link_clk_cnt=%d\n",
		__func__, ctrl->ndx, clk_type, ctrl->bus_clk_cnt,
		ctrl->link_clk_cnt);
	pr_debug("%s++: mctrl=%s m_bus_clk_cnt=%d m_link_clk_cnt=%d, enable=%d\n",
		__func__, mctrl ? "yes" : "no", mctrl ? mctrl->bus_clk_cnt : -1,
		mctrl ? mctrl->link_clk_cnt : -1, enable);

	mutex_lock(&dsi_clk_lock);

	if (clk_type & DSI_BUS_CLKS) {
		bus_changed = __mdss_dsi_update_clk_cnt(&ctrl->bus_clk_cnt,
			enable);
		if (bus_changed && mctrl)
			m_bus_changed = __mdss_dsi_update_clk_cnt(
				&mctrl->bus_clk_cnt, enable);
	}

	if (clk_type & DSI_LINK_CLKS) {
		link_changed = __mdss_dsi_update_clk_cnt(&ctrl->link_clk_cnt,
			enable);
		if (link_changed && mctrl)
			m_link_changed = __mdss_dsi_update_clk_cnt(
				&mctrl->link_clk_cnt, enable);
	}

	if (!link_changed && !bus_changed)
		goto no_error; /* clk cnts updated, nothing else needed */

	/*
	 * If updating link clock, need to make sure that the bus
	 * clocks are enabled
	 */
	if (link_changed && (!bus_changed && !ctrl->bus_clk_cnt)) {
		pr_err("%s: Trying to enable link clks w/o enabling bus clks for ctrl%d",
			__func__, mctrl->ndx);
		goto error_mctrl_start;
	}

	if (m_link_changed && (!m_bus_changed && !mctrl->bus_clk_cnt)) {
		pr_err("%s: Trying to enable link clks w/o enabling bus clks for ctrl%d",
			__func__, ctrl->ndx);
		goto error_mctrl_start;
	}

	if (enable && (m_bus_changed || m_link_changed)) {
		rc = mdss_dsi_clk_ctrl_sub(mctrl, clk_type, enable);
		if (rc) {
			pr_err("Failed to start mctrl clocks. rc=%d\n", rc);
			goto error_mctrl_start;
		}
	}

	if (!enable && (m_bus_changed || m_link_changed)) {
		rc = mdss_dsi_clk_ctrl_sub(mctrl, clk_type, enable);
		if (rc) {
			pr_err("Failed to stop mctrl clocks. rc=%d\n", rc);
			goto error_mctrl_stop;
		}
	}
	rc = mdss_dsi_clk_ctrl_sub(ctrl, clk_type, enable);
	if (rc) {
		pr_err("Failed to %s ctrl clocks. rc=%d\n",
			(enable ? "start" : "stop"), rc);
		goto error_ctrl;
	}

	goto no_error;

error_mctrl_stop:
	mdss_dsi_clk_ctrl_sub(ctrl, clk_type, enable ? 0 : 1);
error_ctrl:
	if (enable && (m_bus_changed || m_link_changed))
		mdss_dsi_clk_ctrl_sub(mctrl, clk_type, 0);
error_mctrl_start:
	if (clk_type & DSI_BUS_CLKS) {
		if (mctrl)
			__mdss_dsi_update_clk_cnt(&mctrl->bus_clk_cnt,
				enable ? 0 : 1);
		__mdss_dsi_update_clk_cnt(&ctrl->bus_clk_cnt, enable ? 0 : 1);
	}
	if (clk_type & DSI_LINK_CLKS) {
		if (mctrl)
			__mdss_dsi_update_clk_cnt(&mctrl->link_clk_cnt,
				enable ? 0 : 1);
		__mdss_dsi_update_clk_cnt(&ctrl->link_clk_cnt, enable ? 0 : 1);
	}

no_error:
	mutex_unlock(&dsi_clk_lock);
	pr_debug("%s--: ndx=%d clk_type=%d bus_clk_cnt=%d link_clk_cnt=%d changed=%d\n",
		__func__, ctrl->ndx, clk_type, ctrl->bus_clk_cnt,
		ctrl->link_clk_cnt, link_changed && bus_changed);
	pr_debug("%s--: mctrl=%s m_bus_clk_cnt=%d m_link_clk_cnt=%d, m_changed=%d, enable=%d\n",
		__func__, mctrl ? "yes" : "no", mctrl ? mctrl->bus_clk_cnt : -1,
		mctrl ? mctrl->link_clk_cnt : -1,
		m_link_changed && m_bus_changed, enable);

	return rc;
}
int mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl,
	u8 clk_type, int enable)
{
	int rc = 0;
	int changed = 0, m_changed = 0;
	struct mdss_dsi_ctrl_pdata *mctrl = NULL;

	if (!ctrl) {
		pr_err("%s: Invalid arg\n", __func__);
		return -EINVAL;
	}

	/*
	 * In broadcast mode, we need to enable clocks for the
	 * master controller as well when enabling clocks for the
	 * slave controller
	 */
	if (mdss_dsi_is_slave_ctrl(ctrl)) {
		mctrl = mdss_dsi_get_master_ctrl();
		if (!mctrl)
			pr_warn("%s: Unable to get master control\n", __func__);
	}

	pr_debug("%s++: ndx=%d clk_type=%d bus_clk_cnt=%d link_clk_cnt=%d",
		__func__, ctrl->ndx, clk_type, ctrl->bus_clk_cnt,
		ctrl->link_clk_cnt);
	pr_debug("%s++: mctrl=%s m_bus_clk_cnt=%d m_link_clk_cnt=%d\n, enable=%d\n",
		__func__, mctrl ? "yes" : "no", mctrl ? mctrl->bus_clk_cnt : -1,
		mctrl ? mctrl->link_clk_cnt : -1, enable);

	mutex_lock(&dsi_clk_lock);
	if (clk_type & DSI_BUS_CLKS) {
		changed = __mdss_dsi_update_clk_cnt(&ctrl->bus_clk_cnt,
			enable);
		if (changed && mctrl)
			m_changed = __mdss_dsi_update_clk_cnt(
				&mctrl->bus_clk_cnt, enable);
	}

	if (clk_type & DSI_LINK_CLKS) {
		changed += __mdss_dsi_update_clk_cnt(&ctrl->link_clk_cnt,
			enable);
		if (changed && mctrl)
			m_changed += __mdss_dsi_update_clk_cnt(
				&mctrl->link_clk_cnt, enable);
	}
#if defined (CONFIG_FB_MSM_MDSS_DSI_DBG)
	xlog(__func__,ctrl->ndx, enable,changed,m_changed,ctrl->bus_clk_cnt,mctrl?mctrl->bus_clk_cnt:0xbbb);
#endif
	if (changed) {
		if (enable && m_changed) {
			rc = mdss_dsi_clk_ctrl_sub(mctrl, clk_type, enable);
			if (rc) {
				pr_err("Failed to start mctrl clocks. rc=%d\n",
					rc);
				goto error_mctrl_start;
			}
		}

		rc = mdss_dsi_clk_ctrl_sub(ctrl, clk_type, enable);
		if (rc) {
			pr_err("Failed to %s ctrl clocks. rc=%d\n",
				(enable ? "start" : "stop"), rc);
			goto error_ctrl;
		}

		if (!enable && m_changed) {
			rc = mdss_dsi_clk_ctrl_sub(mctrl, clk_type, enable);
			if (rc) {
				pr_err("Failed to stop mctrl clocks. rc=%d\n",
					rc);
				goto error_mctrl_stop;
			}
		}
	}
	goto no_error;

error_mctrl_stop:
	mdss_dsi_clk_ctrl_sub(ctrl, clk_type, enable ? 0 : 1);
error_ctrl:
	if (enable && m_changed)
		mdss_dsi_clk_ctrl_sub(mctrl, clk_type, 0);
error_mctrl_start:
	if (clk_type & DSI_BUS_CLKS) {
		if (mctrl)
			__mdss_dsi_update_clk_cnt(&mctrl->bus_clk_cnt,
				enable ? 0 : 1);
		__mdss_dsi_update_clk_cnt(&ctrl->bus_clk_cnt, enable ? 0 : 1);
	}
	if (clk_type & DSI_LINK_CLKS) {
		if (mctrl)
			__mdss_dsi_update_clk_cnt(&mctrl->link_clk_cnt,
				enable ? 0 : 1);
		__mdss_dsi_update_clk_cnt(&ctrl->link_clk_cnt, enable ? 0 : 1);
	}

no_error:
	mutex_unlock(&dsi_clk_lock);
	pr_debug("%s++: ndx=%d clk_type=%d bus_clk_cnt=%d link_clk_cnt=%d changed=%d",
		__func__, ctrl->ndx, clk_type, ctrl->bus_clk_cnt,
		ctrl->link_clk_cnt, changed);
	pr_debug("%s++: mctrl=%s m_bus_clk_cnt=%d m_link_clk_cnt=%d\n, m_changed=%d, enable=%d\n",
		__func__, mctrl ? "yes" : "no", mctrl ? mctrl->bus_clk_cnt : -1,
		mctrl ? mctrl->link_clk_cnt : -1, m_changed, enable);

	return rc;
}