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

Commit 0230a105 authored by Alan Kwong's avatar Alan Kwong
Browse files

drm/msm: add split voting support to sde power handle



Split voting allows separate votes to be applied for
each section of bus paths. This allows better
optimization on bus voting. Add new data bus
identifiers to describe new bus voting topology.
Rename CRTC bandwidth control properties to dram_ab
and dram_ib to better reflect the underlying
hardware being controlled.

CRs-Fixed: 2037879
Change-Id: I43224d3a9cd75334bc8d1031c3eb9b8286d1a376
Signed-off-by: default avatarAlan Kwong <akwong@codeaurora.org>
parent ecd870be
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -29,6 +29,10 @@ Optional properties:
Bus Scaling Subnodes:
- qcom,sde-data-bus:		Property to provide Bus scaling for data bus access for
				sde blocks.
- qcom,sde-llcc-bus:		Property to provide Bus scaling for data bus access for
				mnoc to llcc.
- qcom,sde-ebi-bus:		Property to provide Bus scaling for data bus access for
				llcc to ebi.

Bus Scaling Data:
- qcom,msm-bus,name:		String property describing client name.
@@ -69,4 +73,24 @@ Example:
		          <22 512 0 6400000>, <23 512 0 6400000>,
		          <22 512 0 6400000>, <23 512 0 6400000>;
		};
		qcom,sde-llcc-bus {
			qcom,msm-bus,name = "sde_rsc_llcc";
			qcom,msm-bus,active-only;
			qcom,msm-bus,num-cases = <3>;
			qcom,msm-bus,num-paths = <1>;
			qcom,msm-bus,vectors-KBps =
			    <20001 20513 0 0>,
			    <20001 20513 0 6400000>,
			    <20001 20513 0 6400000>;
		};
		qcom,sde-ebi-bus {
			qcom,msm-bus,name = "sde_rsc_ebi";
			qcom,msm-bus,active-only;
			qcom,msm-bus,num-cases = <3>;
			qcom,msm-bus,num-paths = <1>;
			qcom,msm-bus,vectors-KBps =
			    <20000 20512 0 0>,
			    <20000 20512 0 6400000>,
			    <20000 20512 0 6400000>;
		};
	};
+22 −0
Original line number Diff line number Diff line
@@ -341,6 +341,10 @@ Bus Scaling Subnodes:
				mdss blocks.
- qcom,sde-data-bus:		Property to provide Bus scaling for data bus access for
				mdss blocks.
- qcom,sde-llcc-bus:		Property to provide Bus scaling for data bus access for
				mnoc to llcc.
- qcom,sde-ebi-bus:		Property to provide Bus scaling for data bus access for
				llcc to ebi.

- qcom,sde-inline-rotator:	A 2 cell property, with format of (rotator phandle,
				instance id), of inline rotator device.
@@ -638,6 +642,24 @@ Example:
            <22 512 0 6400000>, <23 512 0 6400000>,
                <25 512 0 6400000>;
    };
    qcom,sde-llcc-bus {
        qcom,msm-bus,name = "mdss_sde_llcc";
        qcom,msm-bus,num-cases = <3>;
        qcom,msm-bus,num-paths = <1>;
        qcom,msm-bus,vectors-KBps =
            <132 770 0 0>,
            <132 770 0 6400000>,
            <132 770 0 6400000>;
    };
    qcom,sde-ebi-bus {
        qcom,msm-bus,name = "mdss_sde_ebi";
        qcom,msm-bus,num-cases = <3>;
        qcom,msm-bus,num-paths = <1>;
        qcom,msm-bus,vectors-KBps =
            <129 512 0 0>,
            <129 512 0 6400000>,
            <129 512 0 6400000>;
    };

    qcom,sde-reg-bus {
        /* Reg Bus Scale Settings */
+4 −2
Original line number Diff line number Diff line
@@ -136,8 +136,10 @@ enum msm_mdp_crtc_property {
	CRTC_PROP_CORE_CLK,
	CRTC_PROP_CORE_AB,
	CRTC_PROP_CORE_IB,
	CRTC_PROP_MEM_AB,
	CRTC_PROP_MEM_IB,
	CRTC_PROP_LLCC_AB,
	CRTC_PROP_LLCC_IB,
	CRTC_PROP_DRAM_AB,
	CRTC_PROP_DRAM_IB,
	CRTC_PROP_ROT_PREFILL_BW,
	CRTC_PROP_ROT_CLK,
	CRTC_PROP_ROI_V1,
+166 −97
Original line number Diff line number Diff line
@@ -110,6 +110,7 @@ static void _sde_core_perf_calc_crtc(struct sde_kms *kms,
		struct sde_core_perf_params *perf)
{
	struct sde_crtc_state *sde_cstate;
	int i;

	if (!kms || !kms->catalog || !crtc || !state || !perf) {
		SDE_ERROR("invalid parameters\n");
@@ -119,29 +120,64 @@ static void _sde_core_perf_calc_crtc(struct sde_kms *kms,
	sde_cstate = to_sde_crtc_state(state);
	memset(perf, 0, sizeof(struct sde_core_perf_params));

	perf->bw_ctl = sde_crtc_get_property(sde_cstate, CRTC_PROP_CORE_AB);
	perf->max_per_pipe_ib =
	perf->bw_ctl[SDE_POWER_HANDLE_DBUS_ID_MNOC] =
		sde_crtc_get_property(sde_cstate, CRTC_PROP_CORE_AB);
	perf->max_per_pipe_ib[SDE_POWER_HANDLE_DBUS_ID_MNOC] =
		sde_crtc_get_property(sde_cstate, CRTC_PROP_CORE_IB);

	if (sde_cstate->bw_split_vote) {
		perf->bw_ctl[SDE_POWER_HANDLE_DBUS_ID_LLCC] =
			sde_crtc_get_property(sde_cstate, CRTC_PROP_LLCC_AB);
		perf->max_per_pipe_ib[SDE_POWER_HANDLE_DBUS_ID_LLCC] =
			sde_crtc_get_property(sde_cstate, CRTC_PROP_LLCC_IB);
		perf->bw_ctl[SDE_POWER_HANDLE_DBUS_ID_EBI] =
			sde_crtc_get_property(sde_cstate, CRTC_PROP_DRAM_AB);
		perf->max_per_pipe_ib[SDE_POWER_HANDLE_DBUS_ID_EBI] =
			sde_crtc_get_property(sde_cstate, CRTC_PROP_DRAM_IB);
	} else {
		perf->bw_ctl[SDE_POWER_HANDLE_DBUS_ID_LLCC] =
			sde_crtc_get_property(sde_cstate, CRTC_PROP_CORE_AB);
		perf->max_per_pipe_ib[SDE_POWER_HANDLE_DBUS_ID_LLCC] =
			sde_crtc_get_property(sde_cstate, CRTC_PROP_CORE_IB);
		perf->bw_ctl[SDE_POWER_HANDLE_DBUS_ID_EBI] =
			sde_crtc_get_property(sde_cstate, CRTC_PROP_CORE_AB);
		perf->max_per_pipe_ib[SDE_POWER_HANDLE_DBUS_ID_EBI] =
			sde_crtc_get_property(sde_cstate, CRTC_PROP_CORE_IB);
	}

	perf->core_clk_rate =
			sde_crtc_get_property(sde_cstate, CRTC_PROP_CORE_CLK);

	if (!sde_cstate->bw_control) {
		perf->bw_ctl = kms->catalog->perf.max_bw_high * 1000ULL;
		perf->max_per_pipe_ib = perf->bw_ctl;
		for (i = 0; i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++) {
			perf->bw_ctl[i] = kms->catalog->perf.max_bw_high *
					1000ULL;
			perf->max_per_pipe_ib[i] = perf->bw_ctl[i];
		}
		perf->core_clk_rate = kms->perf.max_core_clk_rate;
	} else if (kms->perf.perf_tune.mode == SDE_PERF_MODE_MINIMUM) {
		perf->bw_ctl = 0;
		perf->max_per_pipe_ib = 0;
		for (i = 0; i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++) {
			perf->bw_ctl[i] = 0;
			perf->max_per_pipe_ib[i] = 0;
		}
		perf->core_clk_rate = 0;
	} else if (kms->perf.perf_tune.mode == SDE_PERF_MODE_FIXED) {
		perf->bw_ctl = kms->perf.fix_core_ab_vote;
		perf->max_per_pipe_ib = kms->perf.fix_core_ib_vote;
		for (i = 0; i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++) {
			perf->bw_ctl[i] = kms->perf.fix_core_ab_vote;
			perf->max_per_pipe_ib[i] = kms->perf.fix_core_ib_vote;
		}
		perf->core_clk_rate = kms->perf.fix_core_clk_rate;
	}

	SDE_DEBUG("crtc=%d clk_rate=%llu ib=%llu ab=%llu\n",
	SDE_DEBUG(
		"crtc=%d clk_rate=%llu core_ib=%llu core_ab=%llu llcc_ib=%llu llcc_ab=%llu mem_ib=%llu mem_ab=%llu\n",
			crtc->base.id, perf->core_clk_rate,
			perf->max_per_pipe_ib, perf->bw_ctl);
			perf->max_per_pipe_ib[SDE_POWER_HANDLE_DBUS_ID_MNOC],
			perf->bw_ctl[SDE_POWER_HANDLE_DBUS_ID_MNOC],
			perf->max_per_pipe_ib[SDE_POWER_HANDLE_DBUS_ID_LLCC],
			perf->bw_ctl[SDE_POWER_HANDLE_DBUS_ID_LLCC],
			perf->max_per_pipe_ib[SDE_POWER_HANDLE_DBUS_ID_EBI],
			perf->bw_ctl[SDE_POWER_HANDLE_DBUS_ID_EBI]);
}

int sde_core_perf_crtc_check(struct drm_crtc *crtc,
@@ -154,6 +190,7 @@ int sde_core_perf_crtc_check(struct drm_crtc *crtc,
	struct sde_crtc_state *sde_cstate;
	struct drm_crtc *tmp_crtc;
	struct sde_kms *kms;
	int i;

	if (!crtc || !state) {
		SDE_ERROR("invalid crtc\n");
@@ -175,17 +212,21 @@ int sde_core_perf_crtc_check(struct drm_crtc *crtc,
	/* obtain new values */
	_sde_core_perf_calc_crtc(kms, crtc, state, &sde_cstate->new_perf);

	bw_sum_of_intfs = sde_cstate->new_perf.bw_ctl;
	for (i = SDE_POWER_HANDLE_DBUS_ID_MNOC;
			i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++) {
		bw_sum_of_intfs = sde_cstate->new_perf.bw_ctl[i];
		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_get_client_type(tmp_crtc) == curr_client_type) &&
			    (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);

			bw_sum_of_intfs += tmp_cstate->new_perf.bw_ctl;
				bw_sum_of_intfs +=
					tmp_cstate->new_perf.bw_ctl[i];
			}
		}

@@ -196,7 +237,8 @@ int sde_core_perf_crtc_check(struct drm_crtc *crtc,
		is_video_mode = sde_crtc_get_intf_mode(crtc) == INTF_MODE_VIDEO;
		threshold = (is_video_mode ||
			_sde_core_video_mode_intf_connected(crtc)) ?
		kms->catalog->perf.max_bw_low : kms->catalog->perf.max_bw_high;
			kms->catalog->perf.max_bw_low :
			kms->catalog->perf.max_bw_high;

		SDE_DEBUG("final threshold bw limit = %d\n", threshold);

@@ -206,9 +248,11 @@ int sde_core_perf_crtc_check(struct drm_crtc *crtc,
			SDE_ERROR("no bandwidth limits specified\n");
			return -E2BIG;
		} else if (bw > threshold) {
		SDE_ERROR("exceeds bandwidth: %ukb > %ukb\n", bw, threshold);
			SDE_ERROR("exceeds bandwidth: %ukb > %ukb\n", bw,
					threshold);
			return -E2BIG;
		}
	}

	return 0;
}
@@ -240,10 +284,10 @@ static inline enum sde_crtc_client_type _get_sde_client_type(
}

static void _sde_core_perf_crtc_update_bus(struct sde_kms *kms,
		struct drm_crtc *crtc)
		struct drm_crtc *crtc, u32 bus_id)
{
	u64 bw_sum_of_intfs = 0, bus_ab_quota, bus_ib_quota;
	struct sde_core_perf_params perf = {0};
	struct sde_core_perf_params perf = { { 0 } };
	enum sde_crtc_client_type client_vote, curr_client_type
					= sde_crtc_get_client_type(crtc);
	struct drm_crtc *tmp_crtc;
@@ -256,19 +300,20 @@ static void _sde_core_perf_crtc_update_bus(struct sde_kms *kms,
								&kms->perf)) {
			sde_cstate = to_sde_crtc_state(tmp_crtc->state);

			perf.max_per_pipe_ib = max(perf.max_per_pipe_ib,
				sde_cstate->new_perf.max_per_pipe_ib);
			perf.max_per_pipe_ib[bus_id] =
				max(perf.max_per_pipe_ib[bus_id],
				sde_cstate->new_perf.max_per_pipe_ib[bus_id]);

			bw_sum_of_intfs += sde_cstate->new_perf.bw_ctl;
			bw_sum_of_intfs += sde_cstate->new_perf.bw_ctl[bus_id];

			SDE_DEBUG("crtc=%d bw=%llu\n",
				tmp_crtc->base.id,
				sde_cstate->new_perf.bw_ctl);
			SDE_DEBUG("crtc=%d bus_id=%d bw=%llu\n",
				tmp_crtc->base.id, bus_id,
				sde_cstate->new_perf.bw_ctl[bus_id]);
		}
	}

	bus_ab_quota = max(bw_sum_of_intfs, kms->perf.perf_tune.min_bus_vote);
	bus_ib_quota = perf.max_per_pipe_ib;
	bus_ib_quota = perf.max_per_pipe_ib[bus_id];

	if (kms->perf.perf_tune.mode == SDE_PERF_MODE_FIXED) {
		bus_ab_quota = kms->perf.fix_core_ab_vote;
@@ -280,25 +325,25 @@ static void _sde_core_perf_crtc_update_bus(struct sde_kms *kms,
	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);
				bus_id, bus_ab_quota, bus_ib_quota);
		SDE_DEBUG("client:%s bus_id=%d ab=%llu ib=%llu\n", "nrt",
				bus_id, bus_ab_quota, bus_ib_quota);
		break;

	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", "rt",
				bus_ab_quota, bus_ib_quota);
				bus_id, bus_ab_quota, bus_ib_quota);
		SDE_DEBUG("client:%s bus_id=%d ab=%llu ib=%llu\n", "rt",
				bus_id, bus_ab_quota, bus_ib_quota);
		break;

	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);
		sde_rsc_client_vote(sde_cstate->rsc_client,
				bus_id, bus_ab_quota, bus_ib_quota);
		SDE_DEBUG("client:%s bus_id=%d ab=%llu ib=%llu\n", "rt_rsc",
				bus_id, bus_ab_quota, bus_ib_quota);
		break;

	default:
@@ -311,10 +356,12 @@ static void _sde_core_perf_crtc_update_bus(struct sde_kms *kms,
		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_HANDLE_DATA_BUS_CLIENT_NRT,
				bus_id, 0, 0);
			sde_power_data_bus_set_quota(&priv->phandle,
				kms->core_client,
				SDE_POWER_HANDLE_DATA_BUS_CLIENT_RT, 0, 0);
				SDE_POWER_HANDLE_DATA_BUS_CLIENT_RT,
				bus_id, 0, 0);
			kms->perf.bw_vote_mode_updated = false;
			break;

@@ -322,7 +369,7 @@ static void _sde_core_perf_crtc_update_bus(struct sde_kms *kms,
			sde_cstate = to_sde_crtc_state(crtc->state);
			if (sde_cstate->rsc_client) {
				sde_rsc_client_vote(sde_cstate->rsc_client,
									0, 0);
								bus_id, 0, 0);
				kms->perf.bw_vote_mode_updated = false;
			}
			break;
@@ -347,6 +394,7 @@ void sde_core_perf_crtc_release_bw(struct drm_crtc *crtc)
	struct sde_crtc *sde_crtc;
	struct sde_crtc_state *sde_cstate;
	struct sde_kms *kms;
	int i;

	if (!crtc) {
		SDE_ERROR("invalid crtc\n");
@@ -382,9 +430,11 @@ void sde_core_perf_crtc_release_bw(struct drm_crtc *crtc)
	/* Release the bandwidth */
	if (kms->perf.enable_bw_release) {
		trace_sde_cmd_release_bw(crtc->base.id);
		sde_crtc->cur_perf.bw_ctl = 0;
		SDE_DEBUG("Release BW crtc=%d\n", crtc->base.id);
		_sde_core_perf_crtc_update_bus(kms, crtc);
		for (i = 0; i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++) {
			sde_crtc->cur_perf.bw_ctl[i] = 0;
			_sde_core_perf_crtc_update_bus(kms, crtc, i);
		}
	}
}

@@ -419,7 +469,7 @@ void sde_core_perf_crtc_update(struct drm_crtc *crtc,
	u64 clk_rate = 0;
	struct sde_crtc *sde_crtc;
	struct sde_crtc_state *sde_cstate;
	int ret;
	int ret, i;
	struct msm_drm_private *priv;
	struct sde_kms *kms;

@@ -449,6 +499,7 @@ void sde_core_perf_crtc_update(struct drm_crtc *crtc,
	new = &sde_cstate->new_perf;

	if (_sde_core_perf_crtc_is_power_on(crtc) && !stop_req) {
		for (i = 0; i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++) {
			/*
			 * cases for bus bandwidth update.
			 * 1. new bandwidth vote - "ab or ib vote" is higher
@@ -456,31 +507,44 @@ void sde_core_perf_crtc_update(struct drm_crtc *crtc,
			 * 2. new bandwidth vote - "ab or ib vote" is lower
			 *    than current vote at end of commit or stop.
			 */
		if ((params_changed && ((new->bw_ctl > old->bw_ctl) ||
			  (new->max_per_pipe_ib > old->max_per_pipe_ib))) ||
		    (!params_changed && ((new->bw_ctl < old->bw_ctl) ||
			  (new->max_per_pipe_ib < old->max_per_pipe_ib)))) {
			SDE_DEBUG("crtc=%d p=%d new_bw=%llu,old_bw=%llu\n",
				crtc->base.id, params_changed, new->bw_ctl,
				old->bw_ctl);
			old->bw_ctl = new->bw_ctl;
			old->max_per_pipe_ib = new->max_per_pipe_ib;
			update_bus = 1;
			if ((params_changed && ((new->bw_ctl[i] >
						old->bw_ctl[i]) ||
				  (new->max_per_pipe_ib[i] >
						old->max_per_pipe_ib[i]))) ||
			    (!params_changed && ((new->bw_ctl[i] <
						old->bw_ctl[i]) ||
				  (new->max_per_pipe_ib[i] <
						old->max_per_pipe_ib[i])))) {
				SDE_DEBUG(
					"crtc=%d p=%d new_bw=%llu,old_bw=%llu\n",
					crtc->base.id, params_changed,
					new->bw_ctl[i], old->bw_ctl[i]);
				old->bw_ctl[i] = new->bw_ctl[i];
				old->max_per_pipe_ib[i] =
						new->max_per_pipe_ib[i];
				update_bus |= BIT(i);
			}

			/* display rsc override during solver mode */
			if (kms->perf.bw_vote_mode == DISP_RSC_MODE &&
				get_sde_rsc_current_state(SDE_RSC_INDEX) ==
						SDE_RSC_CMD_STATE) {
			/* update new bandwdith in all cases */
			if (params_changed && ((new->bw_ctl != old->bw_ctl) ||
			      (new->max_per_pipe_ib != old->max_per_pipe_ib))) {
				old->bw_ctl = new->bw_ctl;
				old->max_per_pipe_ib = new->max_per_pipe_ib;
				update_bus = 1;
			/* reduce bw vote is not required in solver mode */
				/* update new bandwidth in all cases */
				if (params_changed && ((new->bw_ctl[i] !=
						old->bw_ctl[i]) ||
				      (new->max_per_pipe_ib[i] !=
						old->max_per_pipe_ib[i]))) {
					old->bw_ctl[i] = new->bw_ctl[i];
					old->max_per_pipe_ib[i] =
							new->max_per_pipe_ib[i];
					update_bus |= BIT(i);
				/*
				 * reduce bw vote is not required in solver
				 * mode
				 */
				} else if (!params_changed) {
				update_bus = 0;
					update_bus &= ~BIT(i);
				}
			}
		}

@@ -495,15 +559,20 @@ void sde_core_perf_crtc_update(struct drm_crtc *crtc,
		SDE_DEBUG("crtc=%d disable\n", crtc->base.id);
		memset(old, 0, sizeof(*old));
		memset(new, 0, sizeof(*new));
		update_bus = 1;
		update_bus = ~0;
		update_clk = 1;
	}
	trace_sde_perf_crtc_update(crtc->base.id, new->bw_ctl,
	trace_sde_perf_crtc_update(crtc->base.id,
				new->bw_ctl[SDE_POWER_HANDLE_DBUS_ID_MNOC],
				new->bw_ctl[SDE_POWER_HANDLE_DBUS_ID_LLCC],
				new->bw_ctl[SDE_POWER_HANDLE_DBUS_ID_EBI],
				new->core_clk_rate, stop_req,
				update_bus, update_clk);

	if (update_bus)
		_sde_core_perf_crtc_update_bus(kms, crtc);
	for (i = 0; i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++) {
		if (update_bus & BIT(i))
			_sde_core_perf_crtc_update_bus(kms, crtc, i);
	}

	/*
	 * Update the clock after bandwidth vote to ensure
+2 −2
Original line number Diff line number Diff line
@@ -30,8 +30,8 @@
 * @core_clk_rate: core clock rate request
 */
struct sde_core_perf_params {
	u64 max_per_pipe_ib;
	u64 bw_ctl;
	u64 max_per_pipe_ib[SDE_POWER_HANDLE_DBUS_ID_MAX];
	u64 bw_ctl[SDE_POWER_HANDLE_DBUS_ID_MAX];
	u64 core_clk_rate;
};

Loading