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

Commit dd2032ab authored by Dhaval Patel's avatar Dhaval Patel
Browse files

drm/msm/sde: support bw vote routing through apps and disp rsc



Display has its own rsc. It can route the different displays
bandwidth vote through either apps rsc, display rsc or combine
method. This patch adds the dynamic routing support through
debugfs and dtsi configuration for bandwidth vote routing.

Change-Id: I70cfee784951fd4becf5e817606889e830a134e9
Signed-off-by: default avatarDhaval Patel <pdhaval@codeaurora.org>
parent 68dfac8e
Loading
Loading
Loading
Loading
+84 −5
Original line number Diff line number Diff line
@@ -42,6 +42,23 @@ enum sde_perf_mode {
	SDE_PERF_MODE_MAX
};

/**
 * enum sde_perf_vote_mode: perf vote mode.
 * @APPS_RSC_MODE:	It combines the vote for all displays and votes it
 *                      through APPS rsc. This is default mode when display
 *                      rsc is not available.
 * @DISP_RSC_MODE:	It combines the vote for all displays and votes it
 *                      through display rsc. This is default configuration
 *                      when display rsc is available.
 * @DISP_RSC_PRIMARY_MODE:	The primary display votes through display rsc
 *                      while all other displays votes through apps rsc.
 */
enum sde_perf_vote_mode {
	APPS_RSC_MODE,
	DISP_RSC_MODE,
	DISP_RSC_PRIMARY_MODE,
};

static struct sde_kms *_sde_crtc_get_kms(struct drm_crtc *crtc)
{
	struct msm_drm_private *priv;
@@ -182,12 +199,38 @@ int sde_core_perf_crtc_check(struct drm_crtc *crtc,
	return 0;
}

static inline bool _is_crtc_client_type_matches(struct drm_crtc *tmp_crtc,
	enum sde_crtc_client_type curr_client_type,
	struct sde_core_perf *perf)
{
	if (!tmp_crtc)
		return false;
	else if (perf->bw_vote_mode == DISP_RSC_PRIMARY_MODE &&
							perf->sde_rsc_available)
		return curr_client_type == sde_crtc_get_client_type(tmp_crtc);
	else
		return true;
}

static inline enum sde_crtc_client_type _get_sde_client_type(
	enum sde_crtc_client_type curr_client_type,
	struct sde_core_perf *perf)
{
	if (perf->bw_vote_mode == DISP_RSC_PRIMARY_MODE &&
						perf->sde_rsc_available)
		return curr_client_type;
	else if (perf->bw_vote_mode != APPS_RSC_MODE && perf->sde_rsc_available)
		return RT_RSC_CLIENT;
	else
		return RT_CLIENT;
}

static void _sde_core_perf_crtc_update_bus(struct sde_kms *kms,
		struct drm_crtc *crtc)
{
	u64 bw_sum_of_intfs = 0, bus_ab_quota, bus_ib_quota;
	struct sde_core_perf_params perf = {0};
	enum sde_crtc_client_type curr_client_type
	enum sde_crtc_client_type client_vote, curr_client_type
					= sde_crtc_get_client_type(crtc);
	struct drm_crtc *tmp_crtc;
	struct sde_crtc_state *sde_cstate;
@@ -195,7 +238,8 @@ static void _sde_core_perf_crtc_update_bus(struct sde_kms *kms,

	drm_for_each_crtc(tmp_crtc, crtc->dev) {
		if (_sde_core_perf_crtc_is_power_on(tmp_crtc) &&
		    (curr_client_type == sde_crtc_get_client_type(tmp_crtc))) {
		    _is_crtc_client_type_matches(tmp_crtc, curr_client_type,
								&kms->perf)) {
			sde_cstate = to_sde_crtc_state(tmp_crtc->state);

			perf.max_per_pipe_ib = max(perf.max_per_pipe_ib,
@@ -217,7 +261,8 @@ static void _sde_core_perf_crtc_update_bus(struct sde_kms *kms,
		bus_ib_quota = kms->perf.fix_core_ib_vote;
	}

	switch (curr_client_type) {
	client_vote = _get_sde_client_type(curr_client_type, &kms->perf);
	switch (client_vote) {
	case NRT_CLIENT:
		sde_power_data_bus_set_quota(&priv->phandle, kms->core_client,
				SDE_POWER_HANDLE_DATA_BUS_CLIENT_NRT,
@@ -246,6 +291,32 @@ static void _sde_core_perf_crtc_update_bus(struct sde_kms *kms,
		SDE_ERROR("invalid client type:%d\n", curr_client_type);
		break;
	}

	if (kms->perf.bw_vote_mode_updated) {
		switch (kms->perf.bw_vote_mode) {
		case DISP_RSC_MODE:
			sde_power_data_bus_set_quota(&priv->phandle,
				kms->core_client,
				SDE_POWER_HANDLE_DATA_BUS_CLIENT_NRT, 0, 0);
			sde_power_data_bus_set_quota(&priv->phandle,
				kms->core_client,
				SDE_POWER_HANDLE_DATA_BUS_CLIENT_RT, 0, 0);
			kms->perf.bw_vote_mode_updated = false;
			break;

		case APPS_RSC_MODE:
			sde_cstate = to_sde_crtc_state(crtc->state);
			if (sde_cstate->rsc_client) {
				sde_rsc_client_vote(sde_cstate->rsc_client,
									0, 0);
				kms->perf.bw_vote_mode_updated = false;
			}
			break;

		default:
			break;
		}
	}
}

/**
@@ -535,6 +606,10 @@ int sde_core_perf_debugfs_init(struct sde_core_perf *perf,
			(u32 *)&catalog->perf.max_bw_high);
	debugfs_create_file("perf_mode", 0644, perf->debugfs_root,
			(u32 *)perf, &sde_core_perf_mode_fops);
	debugfs_create_u32("bw_vote_mode", 0600, perf->debugfs_root,
			&perf->bw_vote_mode);
	debugfs_create_bool("bw_vote_mode_updated", 0600, perf->debugfs_root,
			&perf->bw_vote_mode_updated);
	debugfs_create_u64("fix_core_clk_rate", 0644, perf->debugfs_root,
			&perf->fix_core_clk_rate);
	debugfs_create_u64("fix_core_ib_vote", 0644, perf->debugfs_root,
@@ -566,7 +641,6 @@ void sde_core_perf_destroy(struct sde_core_perf *perf)
	sde_core_perf_debugfs_destroy(perf);
	perf->max_core_clk_rate = 0;
	perf->core_clk = NULL;
	mutex_destroy(&perf->perf_lock);
	perf->clk_name = NULL;
	perf->phandle = NULL;
	perf->catalog = NULL;
@@ -590,7 +664,12 @@ int sde_core_perf_init(struct sde_core_perf *perf,
	perf->phandle = phandle;
	perf->pclient = pclient;
	perf->clk_name = clk_name;
	mutex_init(&perf->perf_lock);
	perf->sde_rsc_available = is_sde_rsc_available(SDE_RSC_INDEX);
	/* set default mode */
	if (perf->sde_rsc_available)
		perf->bw_vote_mode = DISP_RSC_MODE;
	else
		perf->bw_vote_mode = APPS_RSC_MODE;

	perf->core_clk = sde_power_clk_get_clk(phandle, clk_name);
	if (!perf->core_clk) {
+6 −2
Original line number Diff line number Diff line
@@ -53,7 +53,6 @@ struct sde_core_perf_tune {
 * struct sde_core_perf - definition of core performance context
 * @dev: Pointer to drm device
 * @debugfs_root: top level debug folder
 * @perf_lock: serialization lock for this context
 * @catalog: Pointer to catalog configuration
 * @phandle: Pointer to power handler
 * @pclient: Pointer to power client
@@ -66,11 +65,13 @@ struct sde_core_perf_tune {
 * @fix_core_clk_rate: fixed core clock request in Hz used in mode 2
 * @fix_core_ib_vote: fixed core ib vote in bps used in mode 2
 * @fix_core_ab_vote: fixed core ab vote in bps used in mode 2
 * @bw_vote_mode: apps rsc vs display rsc bandwidth vote mode
 * @sde_rsc_available: is display rsc available
 * @bw_vote_mode_updated: bandwidth vote mode update
 */
struct sde_core_perf {
	struct drm_device *dev;
	struct dentry *debugfs_root;
	struct mutex perf_lock;
	struct sde_mdss_cfg *catalog;
	struct sde_power_handle *phandle;
	struct sde_power_client *pclient;
@@ -83,6 +84,9 @@ struct sde_core_perf {
	u64 fix_core_clk_rate;
	u64 fix_core_ib_vote;
	u64 fix_core_ab_vote;
	u32 bw_vote_mode;
	bool sde_rsc_available;
	bool bw_vote_mode_updated;
};

/**
+33 −0
Original line number Diff line number Diff line
@@ -215,6 +215,39 @@ void sde_rsc_unregister_event(struct sde_rsc_event *event)
}
EXPORT_SYMBOL(sde_rsc_unregister_event);

bool is_sde_rsc_available(int rsc_index)
{
	if (rsc_index >= MAX_RSC_COUNT) {
		pr_err("invalid rsc index:%d\n", rsc_index);
		return false;
	} else if (!rsc_prv_list[rsc_index]) {
		pr_err("rsc idx:%d not probed yet or not available\n",
								rsc_index);
		return false;
	}

	return true;
}
EXPORT_SYMBOL(is_sde_rsc_available);

enum sde_rsc_state get_sde_rsc_current_state(int rsc_index)
{
	struct sde_rsc_priv *rsc;

	if (rsc_index >= MAX_RSC_COUNT) {
		pr_err("invalid rsc index:%d\n", rsc_index);
		return SDE_RSC_IDLE_STATE;
	} else if (!rsc_prv_list[rsc_index]) {
		pr_err("rsc idx:%d not probed yet or not available\n",
								rsc_index);
		return SDE_RSC_IDLE_STATE;
	}

	rsc = rsc_prv_list[rsc_index];
	return rsc->current_state;
}
EXPORT_SYMBOL(get_sde_rsc_current_state);

static int sde_rsc_clk_enable(struct sde_power_handle *phandle,
	struct sde_power_client *pclient, bool enable)
{
+26 −0
Original line number Diff line number Diff line
@@ -206,6 +206,23 @@ struct sde_rsc_event *sde_rsc_register_event(int rsc_index, uint32_t event_type,
 */
void sde_rsc_unregister_event(struct sde_rsc_event *event);

/**
 * is_sde_rsc_available - check if display rsc available.
 * @rsc_index:   A client will be created on this RSC. As of now only
 *               SDE_RSC_INDEX is valid rsc index.
 * Returns: true if rsc is available; false in all other cases
 */
bool is_sde_rsc_available(int rsc_index);

/**
 * get_sde_rsc_current_state - gets the current state of sde rsc.
 * @rsc_index:   A client will be created on this RSC. As of now only
 *               SDE_RSC_INDEX is valid rsc index.
 * Returns: current state if rsc available; SDE_RSC_IDLE_STATE for
 *          all other cases
 */
enum sde_rsc_state get_sde_rsc_current_state(int rsc_index);

#else

static inline struct sde_rsc_client *sde_rsc_client_create(u32 rsc_index,
@@ -242,6 +259,15 @@ static inline void sde_rsc_unregister_event(struct sde_rsc_event *event)
{
}

static inline bool is_sde_rsc_available(int rsc_index)
{
	return false;
}

static inline enum sde_rsc_state get_sde_rsc_current_state(int rsc_index)
{
	return SDE_RSC_IDLE_STATE;
}
#endif /* CONFIG_DRM_SDE_RSC */

#endif /* _SDE_RSC_H_ */