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

Commit 66a8b75d authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drm/msm/sde: align bandwidth/clock updates with frame done"

parents 0b907764 cf2cb1c3
Loading
Loading
Loading
Loading
+38 −32
Original line number Original line Diff line number Diff line
/* 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
 * 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
 * it under the terms of the GNU General Public License version 2 and
@@ -75,6 +75,31 @@ static bool _sde_core_video_mode_intf_connected(struct drm_crtc *crtc)
	return false;
	return false;
}
}


static void _sde_core_perf_calc_crtc(struct drm_crtc *crtc,
	struct drm_crtc_state *state,
	struct sde_core_perf_params *perf)
{
	struct sde_crtc_state *sde_cstate;

	if (!crtc || !state || !perf) {
		SDE_ERROR("invalid parameters\n");
		return;
	}

	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 =
		sde_crtc_get_property(sde_cstate, CRTC_PROP_CORE_IB);
	perf->core_clk_rate =
		sde_crtc_get_property(sde_cstate, CRTC_PROP_CORE_CLK);

	SDE_DEBUG("crtc=%d clk_rate=%u ib=%llu ab=%llu\n",
			  crtc->base.id, perf->core_clk_rate,
			  perf->max_per_pipe_ib, perf->bw_ctl);
}

int sde_core_perf_crtc_check(struct drm_crtc *crtc,
int sde_core_perf_crtc_check(struct drm_crtc *crtc,
		struct drm_crtc_state *state)
		struct drm_crtc_state *state)
{
{
@@ -102,7 +127,11 @@ int sde_core_perf_crtc_check(struct drm_crtc *crtc,


	sde_cstate = to_sde_crtc_state(state);
	sde_cstate = to_sde_crtc_state(state);


	bw_sum_of_intfs = sde_crtc_get_property(sde_cstate, CRTC_PROP_CORE_AB);
	/* swap state and obtain new values */
	sde_cstate->cur_perf = sde_cstate->new_perf;
	_sde_core_perf_calc_crtc(crtc, state, &sde_cstate->new_perf);

	bw_sum_of_intfs = sde_cstate->new_perf.bw_ctl;


	drm_for_each_crtc(tmp_crtc, crtc->dev) {
	drm_for_each_crtc(tmp_crtc, crtc->dev) {
		if (_sde_core_perf_crtc_is_power_on(tmp_crtc) &&
		if (_sde_core_perf_crtc_is_power_on(tmp_crtc) &&
@@ -110,7 +139,7 @@ int sde_core_perf_crtc_check(struct drm_crtc *crtc,
			struct sde_crtc_state *tmp_cstate =
			struct sde_crtc_state *tmp_cstate =
					to_sde_crtc_state(tmp_crtc->state);
					to_sde_crtc_state(tmp_crtc->state);


			bw_sum_of_intfs += tmp_cstate->cur_perf.bw_ctl;
			bw_sum_of_intfs += tmp_cstate->new_perf.bw_ctl;
		}
		}
	}
	}


@@ -126,11 +155,11 @@ int sde_core_perf_crtc_check(struct drm_crtc *crtc,
	SDE_DEBUG("final threshold bw limit = %d\n", threshold);
	SDE_DEBUG("final threshold bw limit = %d\n", threshold);


	if (!threshold) {
	if (!threshold) {
		sde_cstate->cur_perf.bw_ctl = 0;
		sde_cstate->new_perf = sde_cstate->cur_perf;
		SDE_ERROR("no bandwidth limits specified\n");
		SDE_ERROR("no bandwidth limits specified\n");
		return -E2BIG;
		return -E2BIG;
	} else if (bw > threshold) {
	} else if (bw > threshold) {
		sde_cstate->cur_perf.bw_ctl = 0;
		sde_cstate->new_perf = sde_cstate->cur_perf;
		SDE_DEBUG("exceeds bandwidth: %ukb > %ukb\n", bw, threshold);
		SDE_DEBUG("exceeds bandwidth: %ukb > %ukb\n", bw, threshold);
		return -E2BIG;
		return -E2BIG;
	}
	}
@@ -138,26 +167,6 @@ int sde_core_perf_crtc_check(struct drm_crtc *crtc,
	return 0;
	return 0;
}
}


static void _sde_core_perf_calc_crtc(struct sde_kms *kms,
		struct drm_crtc *crtc,
		struct sde_core_perf_params *perf)
{
	struct sde_crtc_state *sde_cstate;

	sde_cstate = to_sde_crtc_state(crtc->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 =
			sde_crtc_get_property(sde_cstate, CRTC_PROP_CORE_IB);
	perf->core_clk_rate =
			sde_crtc_get_property(sde_cstate, CRTC_PROP_CORE_CLK);

	SDE_DEBUG("crtc=%d clk_rate=%u ib=%llu ab=%llu\n",
			crtc->base.id, perf->core_clk_rate,
			perf->max_per_pipe_ib, perf->bw_ctl);
}

static u64 _sde_core_perf_crtc_calc_client_vote(struct sde_kms *kms,
static u64 _sde_core_perf_crtc_calc_client_vote(struct sde_kms *kms,
		struct drm_crtc *crtc, struct sde_core_perf_params *perf,
		struct drm_crtc *crtc, struct sde_core_perf_params *perf,
		bool nrt_client, u32 core_clk)
		bool nrt_client, u32 core_clk)
@@ -175,13 +184,13 @@ static u64 _sde_core_perf_crtc_calc_client_vote(struct sde_kms *kms,
					to_sde_crtc_state(tmp_crtc->state);
					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);
				sde_cstate->new_perf.max_per_pipe_ib);


			bw_sum_of_intfs += sde_cstate->cur_perf.bw_ctl;
			bw_sum_of_intfs += sde_cstate->new_perf.bw_ctl;


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


@@ -308,7 +317,7 @@ static u32 _sde_core_perf_get_core_clk_rate(struct sde_kms *kms)
	drm_for_each_crtc(crtc, kms->dev) {
	drm_for_each_crtc(crtc, kms->dev) {
		if (_sde_core_perf_crtc_is_power_on(crtc)) {
		if (_sde_core_perf_crtc_is_power_on(crtc)) {
			sde_cstate = to_sde_crtc_state(crtc->state);
			sde_cstate = to_sde_crtc_state(crtc->state);
			clk_rate = max(sde_cstate->cur_perf.core_clk_rate,
			clk_rate = max(sde_cstate->new_perf.core_clk_rate,
							clk_rate);
							clk_rate);
			clk_rate = clk_round_rate(kms->perf.core_clk, clk_rate);
			clk_rate = clk_round_rate(kms->perf.core_clk, clk_rate);
		}
		}
@@ -357,9 +366,6 @@ void sde_core_perf_crtc_update(struct drm_crtc *crtc,
	new = &sde_cstate->new_perf;
	new = &sde_cstate->new_perf;


	if (_sde_core_perf_crtc_is_power_on(crtc) && !stop_req) {
	if (_sde_core_perf_crtc_is_power_on(crtc) && !stop_req) {
		if (params_changed)
			_sde_core_perf_calc_crtc(kms, crtc, new);

		/*
		/*
		 * cases for bus bandwidth update.
		 * cases for bus bandwidth update.
		 * 1. new bandwidth vote or writeback output vote
		 * 1. new bandwidth vote or writeback output vote
+6 −1
Original line number Original line Diff line number Diff line
@@ -473,6 +473,7 @@ static void sde_crtc_frame_event_work(struct kthread_work *work)
	struct sde_crtc_frame_event *fevent;
	struct sde_crtc_frame_event *fevent;
	struct drm_crtc *crtc;
	struct drm_crtc *crtc;
	struct sde_crtc *sde_crtc;
	struct sde_crtc *sde_crtc;
	struct sde_crtc_state *cstate;
	struct sde_kms *sde_kms;
	struct sde_kms *sde_kms;
	unsigned long flags;
	unsigned long flags;


@@ -482,13 +483,14 @@ static void sde_crtc_frame_event_work(struct kthread_work *work)
	}
	}


	fevent = container_of(work, struct sde_crtc_frame_event, work);
	fevent = container_of(work, struct sde_crtc_frame_event, work);
	if (!fevent->crtc) {
	if (!fevent->crtc || !fevent->crtc->state) {
		SDE_ERROR("invalid crtc\n");
		SDE_ERROR("invalid crtc\n");
		return;
		return;
	}
	}


	crtc = fevent->crtc;
	crtc = fevent->crtc;
	sde_crtc = to_sde_crtc(crtc);
	sde_crtc = to_sde_crtc(crtc);
	cstate = to_sde_crtc_state(crtc->state);


	sde_kms = _sde_crtc_get_kms(crtc);
	sde_kms = _sde_crtc_get_kms(crtc);
	if (!sde_kms) {
	if (!sde_kms) {
@@ -522,6 +524,9 @@ static void sde_crtc_frame_event_work(struct kthread_work *work)
		} else {
		} else {
			SDE_EVT32(DRMID(crtc), fevent->event, 2);
			SDE_EVT32(DRMID(crtc), fevent->event, 2);
		}
		}

		if (fevent->event == SDE_ENCODER_FRAME_EVENT_DONE)
			sde_core_perf_crtc_update(crtc, 0, false);
	} else {
	} else {
		SDE_ERROR("crtc%d ts:%lld unknown event %u\n", crtc->base.id,
		SDE_ERROR("crtc%d ts:%lld unknown event %u\n", crtc->base.id,
				ktime_to_ns(fevent->ts),
				ktime_to_ns(fevent->ts),