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

Commit 9329be33 authored by Dhaval Patel's avatar Dhaval Patel Committed by Gerrit - the friendly Code Review server
Browse files

msm: mdss: add reg bus vote to support different frequencies



Current reg bus vote client supports only single frequency
- 19MHz. This is not sufficient for different use cases like
hist update, pp lookup table update during suspend/resume
scenario. A client may request for higher frequency to finish
the job early and avoid glitches. A client based register
voting allows to traverse through votes from each client
and update register bus vote with max client input.

Change-Id: I4e94d1073375dbd71d9ba6268fc8c548ddb67440
Signed-off-by: default avatarDhaval Patel <pdhaval@codeaurora.org>
parent 8cebd075
Loading
Loading
Loading
Loading
+14 −2
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ enum mdss_bus_vote_type {
	VOTE_INDEX_19_MHZ,
	VOTE_INDEX_40_MHZ,
	VOTE_INDEX_80_MHZ,
	VOTE_INDEX_MAX,
};

struct mdss_hw_settings {
@@ -171,10 +172,17 @@ enum mdss_qos_settings {
	MDSS_QOS_MAX,
};

struct reg_bus_client {
	short usecase_ndx;
	u32 id;
	struct list_head list;
};

struct mdss_smmu_client {
	struct device *dev;
	struct dma_iommu_mapping *mmu_mapping;
	struct dss_module_power mp;
	struct reg_bus_client *reg_bus_clt;
	bool domain_attached;
	bool handoff_pending;
};
@@ -298,8 +306,10 @@ struct mdss_data_type {

	/* register bus (AHB) */
	u32 reg_bus_hdl;
	u32 reg_bus_ref_cnt;
	u32 reg_bus_usecase_ndx;
	struct list_head reg_bus_clist;
	struct mutex reg_bus_lock;
	struct reg_bus_client *reg_bus_clt;

	u32 axi_port_cnt;
	u32 nrt_axi_port_cnt;
@@ -437,7 +447,9 @@ struct irq_info *mdss_intr_line(void);
void mdss_bus_bandwidth_ctrl(int enable);
int mdss_iommu_ctrl(int enable);
int mdss_bus_scale_set_quota(int client, u64 ab_quota, u64 ib_quota);
int mdss_update_reg_bus_vote(int usecase_ndx);
int mdss_update_reg_bus_vote(struct reg_bus_client *, u32 usecase_ndx);
struct reg_bus_client *mdss_reg_bus_vote_client_create(void);
void mdss_reg_bus_vote_client_destroy(struct reg_bus_client *);

struct mdss_util_intf {
	bool mdp_probe_done;
+3 −0
Original line number Diff line number Diff line
@@ -249,6 +249,9 @@ struct dsi_shared_data {
	struct clk *byte1_parent;
	struct clk *pixel1_parent;

	/* reg bus clock handle */
	struct reg_bus_client *reg_bus_clt;

	/* DSI core regulators */
	struct dss_module_power power_data[DSI_MAX_PM];

+22 −3
Original line number Diff line number Diff line
@@ -2381,17 +2381,33 @@ static int hdmi_tx_config_power(struct hdmi_tx_ctrl *hdmi_ctrl,
			goto exit;
		}

		hdmi_ctrl->pdata.reg_bus_clt[module] =
			mdss_reg_bus_vote_client_create();
		if (IS_ERR_OR_NULL(hdmi_ctrl->pdata.reg_bus_clt[module])) {
			pr_err("reg bus client create failed\n");
			msm_dss_config_vreg(&hdmi_ctrl->pdev->dev,
			power_data->vreg_config, power_data->num_vreg, 0);
			rc = PTR_ERR(hdmi_ctrl->pdata.reg_bus_clt[module]);
			goto exit;
		}

		rc = msm_dss_get_clk(&hdmi_ctrl->pdev->dev,
			power_data->clk_config, power_data->num_clk);
		if (rc) {
			DEV_ERR("%s: Failed to get %s clk. Err=%d\n",
				__func__, hdmi_tx_pm_name(module), rc);

			mdss_reg_bus_vote_client_destroy(
				hdmi_ctrl->pdata.reg_bus_clt[module]);
			hdmi_ctrl->pdata.reg_bus_clt[module] = NULL;
			msm_dss_config_vreg(&hdmi_ctrl->pdev->dev,
			power_data->vreg_config, power_data->num_vreg, 0);
		}
	} else {
		msm_dss_put_clk(power_data->clk_config, power_data->num_clk);
		mdss_reg_bus_vote_client_destroy(
			hdmi_ctrl->pdata.reg_bus_clt[module]);
		hdmi_ctrl->pdata.reg_bus_clt[module] = NULL;

		rc = msm_dss_config_vreg(&hdmi_ctrl->pdev->dev,
			power_data->vreg_config, power_data->num_vreg, 0);
@@ -2452,7 +2468,8 @@ static int hdmi_tx_enable_power(struct hdmi_tx_ctrl *hdmi_ctrl,
				__func__, hdmi_tx_pm_name(module), rc);
			goto disable_vreg;
		}
		mdss_update_reg_bus_vote(VOTE_INDEX_19_MHZ);
		mdss_update_reg_bus_vote(hdmi_ctrl->pdata.reg_bus_clt[module],
			VOTE_INDEX_19_MHZ);

		rc = msm_dss_clk_set_rate(power_data->clk_config,
			power_data->num_clk);
@@ -2472,7 +2489,8 @@ static int hdmi_tx_enable_power(struct hdmi_tx_ctrl *hdmi_ctrl,
	} else {
		msm_dss_enable_clk(power_data->clk_config,
			power_data->num_clk, 0);
		mdss_update_reg_bus_vote(VOTE_INDEX_DISABLE);
		mdss_update_reg_bus_vote(hdmi_ctrl->pdata.reg_bus_clt[module],
			VOTE_INDEX_DISABLE);
		msm_dss_enable_gpio(power_data->gpio_config,
			power_data->num_gpio, 0);
		hdmi_tx_pinctrl_set_state(hdmi_ctrl, module, 0);
@@ -2483,7 +2501,8 @@ static int hdmi_tx_enable_power(struct hdmi_tx_ctrl *hdmi_ctrl,
	return rc;

disable_gpio:
	mdss_update_reg_bus_vote(VOTE_INDEX_DISABLE);
	mdss_update_reg_bus_vote(hdmi_ctrl->pdata.reg_bus_clt[module],
		VOTE_INDEX_DISABLE);
	msm_dss_enable_gpio(power_data->gpio_config, power_data->num_gpio, 0);
disable_vreg:
	msm_dss_enable_vreg(power_data->vreg_config, power_data->num_vreg, 0);
+1 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ struct hdmi_tx_platform_data {
	bool cond_power_on;
	struct dss_io_data io[HDMI_TX_MAX_IO];
	struct dss_module_power power_data[HDMI_TX_MAX_PM];
	struct reg_bus_client *reg_bus_clt[HDMI_TX_MAX_PM];
	/* bitfield representing each module's pin state */
	u64 pin_states;
};
+70 −23
Original line number Diff line number Diff line
@@ -409,36 +409,74 @@ static int mdss_mdp_bus_scale_set_quota(u64 ab_quota_rt, u64 ab_quota_nrt,
	return rc;
}

int mdss_update_reg_bus_vote(int usecase_ndx)
struct reg_bus_client *mdss_reg_bus_vote_client_create()
{
	int changed = 0, ret = 0;
	struct reg_bus_client *client;
	static u32 id;

	if (!mdss_res || !mdss_res->reg_bus_hdl)
		return 0;
	client = kzalloc(sizeof(struct reg_bus_client), GFP_KERNEL);
	if (!client)
		return ERR_PTR(-ENOMEM);

	mutex_lock(&mdss_res->reg_bus_lock);
	if (usecase_ndx) {
		if (mdss_res->reg_bus_ref_cnt == 0)
			changed++;
		mdss_res->reg_bus_ref_cnt++;
	} else {
		if (mdss_res->reg_bus_ref_cnt) {
			mdss_res->reg_bus_ref_cnt--;
			if (mdss_res->reg_bus_ref_cnt == 0)
				changed++;
	client->usecase_ndx = VOTE_INDEX_DISABLE;
	client->id = id;
	pr_debug("bus vote client created:%p id :%d\n", client, id);
	id++;
	list_add(&client->list, &mdss_res->reg_bus_clist);
	mutex_unlock(&mdss_res->reg_bus_lock);

	return client;
}

void mdss_reg_bus_vote_client_destroy(struct reg_bus_client *client)
{
	if (!client) {
		pr_err("reg bus vote: invalid client handle\n");
	} else {
			pr_err("Can not be turned off\n");
		pr_debug("bus vote client destroyed:%p id:%u\n",
			client, client->id);
		mutex_lock(&mdss_res->reg_bus_lock);
		list_del_init(&client->list);
		mutex_unlock(&mdss_res->reg_bus_lock);
		kfree(client);
	}
}

int mdss_update_reg_bus_vote(struct reg_bus_client *bus_client, u32 usecase_ndx)
{
	int ret = 0;
	bool changed = false;
	u32 max_usecase_ndx = VOTE_INDEX_DISABLE;
	struct reg_bus_client *client, *temp_client;

	if (!mdss_res || !mdss_res->reg_bus_hdl || !bus_client)
		return 0;

	mutex_lock(&mdss_res->reg_bus_lock);
	bus_client->usecase_ndx = usecase_ndx;
	list_for_each_entry_safe(client, temp_client, &mdss_res->reg_bus_clist,
		list) {

		if (client->usecase_ndx < VOTE_INDEX_MAX &&
		    client->usecase_ndx > max_usecase_ndx)
			max_usecase_ndx = client->usecase_ndx;
	}

	if (mdss_res->reg_bus_usecase_ndx != max_usecase_ndx) {
		changed = true;
		mdss_res->reg_bus_usecase_ndx = max_usecase_ndx;
	}

	pr_debug("clk_cnt=%d changed=%d usecase_index=%d\n",
		mdss_res->reg_bus_ref_cnt, changed, usecase_ndx);
	pr_debug("%pS: changed=%d current idx=%d request client id:%u idx:%d\n",
		__builtin_return_address(0), changed, max_usecase_ndx,
		bus_client->id, usecase_ndx);
	MDSS_XLOG(changed, max_usecase_ndx, bus_client->id, usecase_ndx);
	if (changed)
		ret = msm_bus_scale_client_update_request(mdss_res->reg_bus_hdl,
			usecase_ndx);
			max_usecase_ndx);

	mutex_unlock(&mdss_res->reg_bus_lock);

	return ret;
}

@@ -840,7 +878,8 @@ void mdss_mdp_clk_ctrl(int enable)
	if (changed) {
		if (enable) {
			pm_runtime_get_sync(&mdata->pdev->dev);
			mdss_update_reg_bus_vote(VOTE_INDEX_19_MHZ);
			mdss_update_reg_bus_vote(mdata->reg_bus_clt,
				VOTE_INDEX_19_MHZ);
		}

		mdata->clk_ena = enable;
@@ -852,7 +891,8 @@ void mdss_mdp_clk_ctrl(int enable)
			mdss_mdp_clk_update(MDSS_CLK_MDP_VSYNC, enable);

		if (!enable) {
			mdss_update_reg_bus_vote(VOTE_INDEX_DISABLE);
			mdss_update_reg_bus_vote(mdata->reg_bus_clt,
				VOTE_INDEX_DISABLE);
			pm_runtime_mark_last_busy(&mdata->pdev->dev);
			pm_runtime_put_autosuspend(&mdata->pdev->dev);
		}
@@ -894,7 +934,7 @@ static void __mdss_restore_sec_cfg(struct mdss_data_type *mdata)

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

	mdss_update_reg_bus_vote(VOTE_INDEX_19_MHZ);
	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);
@@ -905,7 +945,7 @@ static void __mdss_restore_sec_cfg(struct mdss_data_type *mdata)
				ret, scm_ret);

	mdss_mdp_clk_update(MDSS_CLK_AHB, 0);
	mdss_update_reg_bus_vote(VOTE_INDEX_DISABLE);
	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);
}
@@ -975,6 +1015,12 @@ static int mdss_mdp_irq_clk_setup(struct mdss_data_type *mdata)
		mdata->vdd_cx = NULL;
	}

	mdata->reg_bus_clt = mdss_reg_bus_vote_client_create();
	if (IS_ERR_OR_NULL(mdata->reg_bus_clt)) {
		pr_err("bus client register failed\n");
		return PTR_ERR(mdata->reg_bus_clt);
	}

	if (mdss_mdp_irq_clk_register(mdata, "bus_clk", MDSS_CLK_AXI) ||
	    mdss_mdp_irq_clk_register(mdata, "iface_clk", MDSS_CLK_AHB) ||
	    mdss_mdp_irq_clk_register(mdata, "core_clk",
@@ -1523,6 +1569,7 @@ static int mdss_mdp_probe(struct platform_device *pdev)
	mutex_init(&mdata->reg_lock);
	mutex_init(&mdata->reg_bus_lock);
	mutex_init(&mdata->bus_lock);
	INIT_LIST_HEAD(&mdata->reg_bus_clist);
	atomic_set(&mdata->sd_client_count, 0);
	atomic_set(&mdata->active_intf_cnt, 0);

Loading