drm/msm/sde: cleanup core perf implementation

Current perf and crtc module supports multiple
real time and non-realtime client with different
API checks. These APIs are duplicated and checks
in perf modules are specific to real time vs non-
realtime. This patch cleans up the solution and
make it generalize to support the rsc type bw
client also. A crtc/encoder can now easily switch
between apps rsc vs display rsc by single rsc mode
flag to provide its bandwidth on certain client.

Change-Id: I9e2e09919949bff6e8ca1e5ae7b58449535a4c1a
Signed-off-by: Dhaval Patel <pdhaval@codeaurora.org>
diff --git a/drivers/gpu/drm/msm/sde/sde_core_perf.c b/drivers/gpu/drm/msm/sde/sde_core_perf.c
index 0ba644d..7a68f91 100644
--- a/drivers/gpu/drm/msm/sde/sde_core_perf.c
+++ b/drivers/gpu/drm/msm/sde/sde_core_perf.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, 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
@@ -22,16 +22,10 @@
 #include "msm_prop.h"
 
 #include "sde_kms.h"
-#include "sde_fence.h"
-#include "sde_formats.h"
-#include "sde_hw_sspp.h"
 #include "sde_trace.h"
 #include "sde_crtc.h"
-#include "sde_plane.h"
-#include "sde_encoder.h"
-#include "sde_wb.h"
+#include "sde_rsc.h"
 #include "sde_core_perf.h"
-#include "sde_trace.h"
 
 static struct sde_kms *_sde_crtc_get_kms(struct drm_crtc *crtc)
 {
@@ -59,20 +53,23 @@
 static bool _sde_core_video_mode_intf_connected(struct drm_crtc *crtc)
 {
 	struct drm_crtc *tmp_crtc;
+	bool intf_connected = false;
 
 	if (!crtc)
-		return 0;
+		goto end;
 
 	drm_for_each_crtc(tmp_crtc, crtc->dev) {
 		if ((sde_crtc_get_intf_mode(tmp_crtc) == INTF_MODE_VIDEO) &&
 				_sde_core_perf_crtc_is_power_on(tmp_crtc)) {
 			SDE_DEBUG("video interface connected crtc:%d\n",
 				tmp_crtc->base.id);
-			return true;
+			intf_connected = true;
+			goto end;
 		}
 	}
 
-	return false;
+end:
+	return intf_connected;
 }
 
 int sde_core_perf_crtc_check(struct drm_crtc *crtc,
@@ -80,6 +77,7 @@
 {
 	u32 bw, threshold;
 	u64 bw_sum_of_intfs = 0;
+	enum sde_crtc_client_type curr_client_type;
 	bool is_video_mode;
 	struct sde_crtc_state *sde_cstate;
 	struct drm_crtc *tmp_crtc;
@@ -97,16 +95,18 @@
 	}
 
 	/* we only need bandwidth check on real-time clients (interfaces) */
-	if (sde_crtc_is_wb(crtc))
+	if (sde_crtc_get_client_type(crtc) == NRT_CLIENT)
 		return 0;
 
 	sde_cstate = to_sde_crtc_state(state);
 
 	bw_sum_of_intfs = sde_crtc_get_property(sde_cstate, CRTC_PROP_CORE_AB);
+	curr_client_type = sde_crtc_get_client_type(crtc);
 
 	drm_for_each_crtc(tmp_crtc, crtc->dev) {
 		if (_sde_core_perf_crtc_is_power_on(tmp_crtc) &&
-				sde_crtc_is_rt(tmp_crtc) && tmp_crtc != crtc) {
+		    (sde_crtc_get_client_type(tmp_crtc) == curr_client_type) &&
+		    (tmp_crtc != crtc)) {
 			struct sde_crtc_state *tmp_cstate =
 					to_sde_crtc_state(tmp_crtc->state);
 
@@ -131,7 +131,7 @@
 		return -E2BIG;
 	} else if (bw > threshold) {
 		sde_cstate->cur_perf.bw_ctl = 0;
-		SDE_DEBUG("exceeds bandwidth: %ukb > %ukb\n", bw, threshold);
+		SDE_ERROR("exceeds bandwidth: %ukb > %ukb\n", bw, threshold);
 		return -E2BIG;
 	}
 
@@ -158,23 +158,23 @@
 			perf->max_per_pipe_ib, perf->bw_ctl);
 }
 
-static u64 _sde_core_perf_crtc_calc_client_vote(struct sde_kms *kms,
-		struct drm_crtc *crtc, struct sde_core_perf_params *perf,
-		bool nrt_client, u32 core_clk)
+static void _sde_core_perf_crtc_update_bus(struct sde_kms *kms,
+		struct drm_crtc *crtc)
 {
-	u64 bw_sum_of_intfs = 0;
+	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
+					= sde_crtc_get_client_type(crtc);
 	struct drm_crtc *tmp_crtc;
+	struct sde_crtc_state *sde_cstate;
+	struct msm_drm_private *priv = kms->dev->dev_private;
 
 	drm_for_each_crtc(tmp_crtc, crtc->dev) {
-		if (_sde_core_perf_crtc_is_power_on(crtc) &&
-		    /* RealTime clients */
-		    ((!nrt_client) ||
-		    /* Non-RealTime clients */
-		    (nrt_client && sde_crtc_is_nrt(tmp_crtc)))) {
-			struct sde_crtc_state *sde_cstate =
-					to_sde_crtc_state(tmp_crtc->state);
+		if (_sde_core_perf_crtc_is_power_on(tmp_crtc) &&
+		    (curr_client_type == sde_crtc_get_client_type(tmp_crtc))) {
+			sde_cstate = to_sde_crtc_state(tmp_crtc->state);
 
-			perf->max_per_pipe_ib = max(perf->max_per_pipe_ib,
+			perf.max_per_pipe_ib = max(perf.max_per_pipe_ib,
 				sde_cstate->cur_perf.max_per_pipe_ib);
 
 			bw_sum_of_intfs += sde_cstate->cur_perf.bw_ctl;
@@ -185,57 +185,38 @@
 		}
 	}
 
-	return bw_sum_of_intfs;
-}
+	bus_ab_quota = max(bw_sum_of_intfs, kms->perf.perf_tune.min_bus_vote);
+	bus_ib_quota = perf.max_per_pipe_ib;
 
-static void _sde_core_perf_crtc_update_client_vote(struct sde_kms *kms,
-	struct sde_core_perf_params *params, bool nrt_client, u64 bw_vote)
-{
-	struct msm_drm_private *priv = kms->dev->dev_private;
-	u64 bus_ab_quota, bus_ib_quota;
+	switch (curr_client_type) {
+	case NRT_CLIENT:
+		sde_power_data_bus_set_quota(&priv->phandle, kms->core_client,
+				SDE_POWER_HANDLE_DATA_BUS_CLIENT_NRT,
+				bus_ab_quota, bus_ib_quota);
+		SDE_DEBUG("client:%s ab=%llu ib=%llu\n", "nrt",
+				bus_ab_quota, bus_ib_quota);
+		break;
 
-	bus_ab_quota = max(bw_vote, kms->perf.perf_tune.min_bus_vote);
-	bus_ib_quota = params->max_per_pipe_ib;
-
-	SDE_ATRACE_INT("bus_quota", bus_ib_quota);
-	sde_power_data_bus_set_quota(&priv->phandle, kms->core_client,
-		nrt_client ? SDE_POWER_HANDLE_DATA_BUS_CLIENT_NRT :
+	case RT_CLIENT:
+		sde_power_data_bus_set_quota(&priv->phandle, kms->core_client,
 				SDE_POWER_HANDLE_DATA_BUS_CLIENT_RT,
-		bus_ab_quota, bus_ib_quota);
-	SDE_DEBUG("client:%s ab=%llu ib=%llu\n", nrt_client ? "nrt" : "rt",
-		bus_ab_quota, bus_ib_quota);
-}
+				bus_ab_quota, bus_ib_quota);
+		SDE_DEBUG("client:%s ab=%llu ib=%llu\n", "rt",
+				bus_ab_quota, bus_ib_quota);
+		break;
 
-static void _sde_core_perf_crtc_update_bus(struct sde_kms *kms,
-		struct drm_crtc *crtc, u32 core_clk)
-{
-	u64 bw_sum_of_rt_intfs = 0, bw_sum_of_nrt_intfs = 0;
-	struct sde_core_perf_params params = {0};
+	case RT_RSC_CLIENT:
+		sde_cstate = to_sde_crtc_state(crtc->state);
+		sde_rsc_client_vote(sde_cstate->rsc_client, bus_ab_quota,
+					bus_ib_quota);
+		SDE_DEBUG("client:%s ab=%llu ib=%llu\n", "rt_rsc",
+				bus_ab_quota, bus_ib_quota);
+		break;
 
-	SDE_ATRACE_BEGIN(__func__);
-
-	/*
-	 * non-real time client
-	 */
-	if (sde_crtc_is_nrt(crtc)) {
-		bw_sum_of_nrt_intfs = _sde_core_perf_crtc_calc_client_vote(
-				kms, crtc, &params, true, core_clk);
-		_sde_core_perf_crtc_update_client_vote(kms, &params, true,
-			bw_sum_of_nrt_intfs);
+	default:
+		SDE_ERROR("invalid client type:%d\n", curr_client_type);
+		break;
 	}
-
-	/*
-	 * real time client
-	 */
-	if (!sde_crtc_is_nrt(crtc) ||
-		sde_crtc_is_wb(crtc)) {
-		bw_sum_of_rt_intfs = _sde_core_perf_crtc_calc_client_vote(kms,
-				crtc, &params, false, core_clk);
-		_sde_core_perf_crtc_update_client_vote(kms, &params, false,
-			bw_sum_of_rt_intfs);
-	}
-
-	SDE_ATRACE_END(__func__);
 }
 
 /**
@@ -265,9 +246,9 @@
 
 	sde_cstate = to_sde_crtc_state(crtc->state);
 
-	/* only do this for command panel or writeback */
+	/* only do this for command mode rt client (non-rsc client) */
 	if ((sde_crtc_get_intf_mode(crtc) != INTF_MODE_CMD) &&
-			(sde_crtc_get_intf_mode(crtc) != INTF_MODE_WB_LINE))
+		(sde_crtc_get_client_type(crtc) != RT_RSC_CLIENT))
 		return;
 
 	/*
@@ -288,22 +269,15 @@
 		sde_cstate->cur_perf.bw_ctl = 0;
 		sde_cstate->new_perf.bw_ctl = 0;
 		SDE_DEBUG("Release BW crtc=%d\n", crtc->base.id);
-		_sde_core_perf_crtc_update_bus(kms, crtc, 0);
+		_sde_core_perf_crtc_update_bus(kms, crtc);
 	}
 }
 
-static int _sde_core_select_clk_lvl(struct sde_kms *kms,
-			u32 clk_rate)
-{
-	return clk_round_rate(kms->perf.core_clk, clk_rate);
-}
-
 static u32 _sde_core_perf_get_core_clk_rate(struct sde_kms *kms)
 {
 	u32 clk_rate = 0;
 	struct drm_crtc *crtc;
 	struct sde_crtc_state *sde_cstate;
-	int ncrtc = 0;
 
 	drm_for_each_crtc(crtc, kms->dev) {
 		if (_sde_core_perf_crtc_is_power_on(crtc)) {
@@ -312,11 +286,9 @@
 							clk_rate);
 			clk_rate = clk_round_rate(kms->perf.core_clk, clk_rate);
 		}
-		ncrtc++;
 	}
-	clk_rate = _sde_core_select_clk_lvl(kms, clk_rate);
 
-	SDE_DEBUG("clk:%u ncrtc:%d\n", clk_rate, ncrtc);
+	SDE_DEBUG("clk:%u\n", clk_rate);
 
 	return clk_rate;
 }
@@ -351,8 +323,6 @@
 	SDE_DEBUG("crtc:%d stop_req:%d core_clk:%u\n",
 			crtc->base.id, stop_req, kms->perf.core_clk_rate);
 
-	SDE_ATRACE_BEGIN(__func__);
-
 	old = &sde_cstate->cur_perf;
 	new = &sde_cstate->new_perf;
 
@@ -392,38 +362,28 @@
 		update_clk = 1;
 	}
 
-	/*
-	 * Calculate mdp clock before bandwidth calculation. If traffic shaper
-	 * is enabled and clock increased, the bandwidth calculation can
-	 * use the new clock for the rotator bw calculation.
-	 */
-	if (update_clk)
-		clk_rate = _sde_core_perf_get_core_clk_rate(kms);
-
 	if (update_bus)
-		_sde_core_perf_crtc_update_bus(kms, crtc, clk_rate);
+		_sde_core_perf_crtc_update_bus(kms, crtc);
 
 	/*
 	 * Update the clock after bandwidth vote to ensure
 	 * bandwidth is available before clock rate is increased.
 	 */
 	if (update_clk) {
-		SDE_ATRACE_INT(kms->perf.clk_name, clk_rate);
+		clk_rate = _sde_core_perf_get_core_clk_rate(kms);
+
 		SDE_EVT32(kms->dev, stop_req, clk_rate);
 		ret = sde_power_clk_set_rate(&priv->phandle,
 				kms->perf.clk_name, clk_rate);
 		if (ret) {
 			SDE_ERROR("failed to set %s clock rate %u\n",
 					kms->perf.clk_name, clk_rate);
-			goto end;
+			return;
 		}
 
 		kms->perf.core_clk_rate = clk_rate;
 		SDE_DEBUG("update clk rate = %d HZ\n", clk_rate);
 	}
-
-end:
-	SDE_ATRACE_END(__func__);
 }
 
 #ifdef CONFIG_DEBUG_FS
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index ed9fd5d..7563074 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -417,7 +417,6 @@
 	SDE_EVT32(DRMID(crtc));
 
 	/* identify connectors attached to this crtc */
-	cstate->is_rt = false;
 	cstate->num_connectors = 0;
 
 	drm_for_each_connector(conn, crtc->dev)
@@ -425,9 +424,6 @@
 				cstate->num_connectors < MAX_CONNECTORS) {
 			cstate->connectors[cstate->num_connectors++] = conn;
 			sde_connector_prepare_fence(conn);
-
-			if (conn->connector_type != DRM_MODE_CONNECTOR_VIRTUAL)
-				cstate->is_rt = true;
 		}
 
 	if (cstate->num_connectors > 0 && cstate->connectors[0]->encoder)
@@ -440,15 +436,6 @@
 	sde_fence_prepare(&sde_crtc->output_fence);
 }
 
-bool sde_crtc_is_rt(struct drm_crtc *crtc)
-{
-	if (!crtc || !crtc->state) {
-		SDE_ERROR("invalid crtc or state\n");
-		return true;
-	}
-	return to_sde_crtc_state(crtc->state)->is_rt;
-}
-
 /* if file!=NULL, this is preclose potential cancel-flip path */
 static void _sde_crtc_complete_flip(struct drm_crtc *crtc,
 		struct drm_file *file)
@@ -1869,7 +1856,7 @@
 	struct sde_crtc_state *cstate = to_sde_crtc_state(crtc->state);
 
 	seq_printf(s, "num_connectors: %d\n", cstate->num_connectors);
-	seq_printf(s, "is_rt: %d\n", cstate->is_rt);
+	seq_printf(s, "client type: %d\n", sde_crtc_get_client_type(crtc));
 	seq_printf(s, "intf_mode: %d\n", cstate->intf_mode);
 	seq_printf(s, "bw_ctl: %llu\n", cstate->cur_perf.bw_ctl);
 	seq_printf(s, "core_clk_rate: %u\n", cstate->cur_perf.core_clk_rate);
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h
index 91fdaed..f254977 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.h
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.h
@@ -31,6 +31,20 @@
 #define SDE_CRTC_FRAME_EVENT_SIZE	2
 
 /**
+ * enum sde_crtc_client_type: crtc client type
+ * @RT_CLIENT:	RealTime client like video/cmd mode display
+ *              voting through apps rsc
+ * @NRT_CLIENT:	Non-RealTime client like WB display
+ *              voting through apps rsc
+ * @RT_RSC_CLIENT:	Realtime display RSC voting client
+ */
+enum sde_crtc_client_type {
+	RT_CLIENT,
+	NRT_CLIENT,
+	RT_RSC_CLIENT,
+};
+
+/**
  * struct sde_crtc_mixer: stores the map for each virtual pipeline in the CRTC
  * @hw_lm:	LM HW Driver context
  * @hw_ctl:	CTL Path HW driver context
@@ -136,8 +150,9 @@
  * @base: Base drm crtc state structure
  * @connectors    : Currently associated drm connectors
  * @num_connectors: Number of associated drm connectors
- * @is_rt         : Whether or not the current commit contains RT connectors
  * @intf_mode     : Interface mode of the primary connector
+ * @rsc_mode      : Client vote through sde rsc
+ * @rsc_client    : sde rsc client when mode is valid
  * @property_values: Current crtc property values
  * @input_fence_timeout_ns : Cached input fence timeout, in ns
  * @property_blobs: Reference pointers for blob properties
@@ -151,8 +166,9 @@
 
 	struct drm_connector *connectors[MAX_CONNECTORS];
 	int num_connectors;
-	bool is_rt;
 	enum sde_intf_mode intf_mode;
+	bool rsc_mode;
+	struct sde_rsc_client *rsc_client;
 
 	uint64_t property_values[CRTC_PROP_COUNT];
 	uint64_t input_fence_timeout_ns;
@@ -255,13 +271,6 @@
 void sde_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file);
 
 /**
- * sde_crtc_is_rt - query whether real time connectors are present on the crtc
- * @crtc: Pointer to drm crtc structure
- * Returns: True if a connector is present with real time constraints
- */
-bool sde_crtc_is_rt(struct drm_crtc *crtc);
-
-/**
  * sde_crtc_get_intf_mode - get interface mode of the given crtc
  * @crtc: Pointert to crtc
  */
@@ -274,24 +283,16 @@
 }
 
 /**
- * sde_core_perf_crtc_is_wb - check if writeback is primary output of this crtc
+ * sde_crtc_get_client_type - check the crtc type- rt, nrt, rsc, etc.
  * @crtc: Pointer to crtc
  */
-static inline bool sde_crtc_is_wb(struct drm_crtc *crtc)
+static inline bool sde_crtc_get_client_type(struct drm_crtc *crtc)
 {
 	struct sde_crtc_state *cstate =
 			crtc ? to_sde_crtc_state(crtc->state) : NULL;
 
-	return cstate ? (cstate->intf_mode == INTF_MODE_WB_LINE) : false;
-}
-
-/**
- * sde_crtc_is_nrt - check if primary output of this crtc is non-realtime client
- * @crtc: Pointer to crtc
- */
-static inline bool sde_crtc_is_nrt(struct drm_crtc *crtc)
-{
-	return sde_crtc_is_wb(crtc);
+	return cstate && (cstate->intf_mode == INTF_MODE_WB_LINE) ? NRT_CLIENT
+		: cstate && cstate->rsc_mode ? RT_RSC_CLIENT : RT_CLIENT;
 }
 
 /**
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index d22c93f..6a31e1d 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -862,8 +862,7 @@
 	if (sde_enc->disp_info.is_primary) {
 		ret = sde_rsc_client_vote(sde_enc->rsc_client,
 			SDE_POWER_HANDLE_DATA_BUS_IB_QUOTA,
-			SDE_POWER_HANDLE_DATA_BUS_AB_QUOTA,
-			true);
+			SDE_POWER_HANDLE_DATA_BUS_AB_QUOTA);
 		if (ret)
 			SDE_ERROR("sde rsc client vote failed ret:%d\n", ret);
 	}
@@ -1303,7 +1302,6 @@
 	}
 	mutex_unlock(&sde_enc->enc_lock);
 
-
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c
index e144a0d..46508c7b 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.c
@@ -1203,7 +1203,7 @@
 		return 0;
 	pstate->pending = true;
 
-	psde->is_rt_pipe = sde_crtc_is_rt(crtc);
+	psde->is_rt_pipe = (sde_crtc_get_client_type(crtc) != NRT_CLIENT);
 	_sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
 
 	/* update roi config */
diff --git a/drivers/gpu/drm/msm/sde_rsc.c b/drivers/gpu/drm/msm/sde_rsc.c
index 9a96c64..3c00499 100644
--- a/drivers/gpu/drm/msm/sde_rsc.c
+++ b/drivers/gpu/drm/msm/sde_rsc.c
@@ -406,7 +406,7 @@
  * Return: error code.
  */
 int sde_rsc_client_vote(struct sde_rsc_client *caller_client,
-	u64 ab_vote, u64 ib_vote, bool active)
+	u64 ab_vote, u64 ib_vote)
 {
 	int rc = 0;
 	struct sde_rsc_priv *rsc;
@@ -447,15 +447,11 @@
 		amc_mode = rsc->hw_ops.is_amc_mode(rsc);
 
 	if (rsc->current_state == SDE_RSC_CMD_STATE)
-		if (active)
-			state = RPMH_WAKE_ONLY_STATE;
-		else
-			state = RPMH_SLEEP_STATE;
+		state = RPMH_WAKE_ONLY_STATE;
+	else if (amc_mode)
+		state = RPMH_ACTIVE_ONLY_STATE;
 	else
-		if (amc_mode)
-			state = RPMH_ACTIVE_ONLY_STATE;
-		else
-			state = RPMH_AWAKE_STATE;
+		state = RPMH_AWAKE_STATE;
 
 	if (rsc->hw_ops.tcs_wait) {
 		rc = rsc->hw_ops.tcs_wait(rsc);
diff --git a/drivers/gpu/drm/msm/sde_rsc.h b/drivers/gpu/drm/msm/sde_rsc.h
index 91dff46..399b392 100644
--- a/drivers/gpu/drm/msm/sde_rsc.h
+++ b/drivers/gpu/drm/msm/sde_rsc.h
@@ -281,12 +281,11 @@
  * @client:	 Client pointer provided by sde_rsc_client_create().
  * @ab:		 aggregated bandwidth vote from client.
  * @ib:		 instant bandwidth vote from client.
- * @active:	 tcs command set selected based on active vs sleep request
  *
  * Return: error code.
  */
 int sde_rsc_client_vote(struct sde_rsc_client *caller_client,
-	u64 ab_vote, u64 ib_vote, bool active);
+	u64 ab_vote, u64 ib_vote);
 
 /**
  * sde_rsc_hw_register() - register hardware API