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

Commit 5fc49fcc authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drm/msm/sde: add support for true inline rotation"

parents f1fb1191 36a32948
Loading
Loading
Loading
Loading
+131 −2
Original line number Diff line number Diff line
@@ -12,6 +12,8 @@
#include <linux/clk.h>
#include <linux/bitmap.h>
#include <linux/sde_rsc.h>
#include <linux/platform_device.h>
#include <linux/soc/qcom/llcc-qcom.h>

#include "msm_prop.h"

@@ -297,6 +299,107 @@ static inline enum sde_crtc_client_type _get_sde_client_type(
		return RT_CLIENT;
}

/**
 * @_sde_core_perf_activate_llcc() - Activates/deactivates the system llcc
 * @kms - pointer to the kms
 * @uid - ID for which the llcc would be activated
 * @activate - boolean to indicate if activate/deactivate the LLCC
 *
 * Function assumes that caller has already acquired the "sde_core_perf_lock",
 * which would protect from any race condition between CRTC's
 */
static int _sde_core_perf_activate_llcc(struct sde_kms *kms,
	u32 uid, bool activate)
{
	struct llcc_slice_desc *slice;
	struct drm_device *drm_dev;
	struct device *dev;
	struct platform_device *pdev;
	int rc = 0;

	if (!kms || !kms->dev || !kms->dev->dev) {
		SDE_ERROR("wrong params won't activate llcc\n");
		rc = -EINVAL;
		goto exit;
	}

	drm_dev = kms->dev;
	dev = drm_dev->dev;
	pdev = to_platform_device(dev);

	/* If LLCC is already in the requested state, skip */
	SDE_EVT32(activate, kms->perf.llcc_active);
	if ((activate && kms->perf.llcc_active) ||
		(!activate && !kms->perf.llcc_active)) {
		SDE_DEBUG("skip llcc request:%d state:%d\n",
			activate, kms->perf.llcc_active);
		goto exit;
	}

	SDE_DEBUG("activate/deactivate the llcc request:%d state:%d\n",
		activate, kms->perf.llcc_active);

	slice = llcc_slice_getd(uid);
	if (IS_ERR_OR_NULL(slice))  {
		SDE_ERROR("failed to get llcc slice for uid:%d\n", uid);
		rc = -EINVAL;
		goto exit;
	}

	if (activate) {
		llcc_slice_activate(slice);
		kms->perf.llcc_active = true;
	} else {
		llcc_slice_deactivate(slice);
		kms->perf.llcc_active = false;
	}

exit:
	if (rc)
		SDE_ERROR("error activating llcc:%d rc:%d\n",
			activate, rc);
	return rc;

}

static void _sde_core_perf_crtc_update_llcc(struct sde_kms *kms,
		struct drm_crtc *crtc)
{
	struct drm_crtc *tmp_crtc;
	struct sde_crtc *sde_crtc;
	enum sde_crtc_client_type curr_client_type
					= sde_crtc_get_client_type(crtc);
	u32 total_llcc_active = 0;

	if (!kms->perf.catalog->sc_cfg.has_sys_cache) {
		SDE_DEBUG("System Cache is not enabled!. Won't use\n");
		return;
	}

	drm_for_each_crtc(tmp_crtc, crtc->dev) {
		if (_sde_core_perf_crtc_is_power_on(tmp_crtc) &&
			_is_crtc_client_type_matches(tmp_crtc, curr_client_type,
								&kms->perf)) {

			/* use current perf, which are the values voted */
			sde_crtc = to_sde_crtc(tmp_crtc);
			total_llcc_active |=
			  sde_crtc->cur_perf.llcc_active;

			SDE_DEBUG("crtc=%d llcc:%llu active:0x%x\n",
				tmp_crtc->base.id,
				sde_crtc->cur_perf.llcc_active,
				total_llcc_active);

			if (total_llcc_active)
				break;
		}
	}

	_sde_core_perf_activate_llcc(kms, LLCC_ROTATOR,
			total_llcc_active ? true : false);
}

static void _sde_core_perf_crtc_update_bus(struct sde_kms *kms,
		struct drm_crtc *crtc, u32 bus_id)
{
@@ -494,7 +597,7 @@ void sde_core_perf_crtc_update(struct drm_crtc *crtc,
		int params_changed, bool stop_req)
{
	struct sde_core_perf_params *new, *old;
	int update_bus = 0, update_clk = 0;
	int update_bus = 0, update_clk = 0, update_llcc = 0;
	u64 clk_rate = 0;
	struct sde_crtc *sde_crtc;
	struct sde_crtc_state *sde_cstate;
@@ -534,6 +637,28 @@ void sde_core_perf_crtc_update(struct drm_crtc *crtc,
	new = &sde_crtc->new_perf;

	if (_sde_core_perf_crtc_is_power_on(crtc) && !stop_req) {

		/*
		 * cases for the llcc update.
		 * 1. llcc is transitioning: 'inactive->active' during kickoff,
		 *	for current request.
		 * 2. llcc is transitioning: 'active->inactive'at the end of the
		 *	commit or during stop
		 */

		if ((params_changed &&
			 new->llcc_active && !old->llcc_active) ||
		    (!params_changed &&
			!new->llcc_active && old->llcc_active)) {

			SDE_DEBUG("crtc=%d p=%d new_llcc=%d, old_llcc=%d\n",
				crtc->base.id, params_changed,
				new->llcc_active, old->llcc_active);

			old->llcc_active = new->llcc_active;
			update_llcc = 1;
		}

		for (i = 0; i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++) {
			/*
			 * cases for bus bandwidth update.
@@ -604,11 +729,12 @@ void sde_core_perf_crtc_update(struct drm_crtc *crtc,
			update_clk = 1;
		}
	} else {
		SDE_DEBUG("crtc=%d disable\n", crtc->base.id);
		SDE_ERROR("crtc=%d disable\n", crtc->base.id);
		memset(old, 0, sizeof(*old));
		memset(new, 0, sizeof(*new));
		update_bus = ~0;
		update_clk = 1;
		update_llcc = 1;
	}
	trace_sde_perf_crtc_update(crtc->base.id,
		new->bw_ctl[SDE_POWER_HANDLE_DBUS_ID_MNOC],
@@ -620,6 +746,9 @@ void sde_core_perf_crtc_update(struct drm_crtc *crtc,
		new->core_clk_rate, stop_req,
		update_bus, update_clk, params_changed);

	if (update_llcc)
		_sde_core_perf_crtc_update_llcc(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);
+4 −0
Original line number Diff line number Diff line
@@ -21,11 +21,13 @@
 * @max_per_pipe_ib: maximum instantaneous bandwidth request
 * @bw_ctl: arbitrated bandwidth request
 * @core_clk_rate: core clock rate request
 * @llcc_active: request to activate/deactivate the llcc
 */
struct sde_core_perf_params {
	u64 max_per_pipe_ib[SDE_POWER_HANDLE_DBUS_ID_MAX];
	u64 bw_ctl[SDE_POWER_HANDLE_DBUS_ID_MAX];
	u64 core_clk_rate;
	bool llcc_active;
};

/**
@@ -59,6 +61,7 @@ struct sde_core_perf_tune {
 * @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
 * @llcc_active: status of the llcc, true if active.
 */
struct sde_core_perf {
	struct drm_device *dev;
@@ -78,6 +81,7 @@ struct sde_core_perf {
	u32 bw_vote_mode;
	bool sde_rsc_available;
	bool bw_vote_mode_updated;
	bool llcc_active;
};

/**
+19 −2
Original line number Diff line number Diff line
@@ -1234,7 +1234,8 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc,
				state->src_x >> 16, state->src_y >> 16,
				state->src_w >> 16, state->src_h >> 16,
				state->crtc_x, state->crtc_y,
				state->crtc_w, state->crtc_h);
				state->crtc_w, state->crtc_h,
				pstate->rotation);

		stage_idx = zpos_cnt[pstate->stage]++;
		stage_cfg->stage[pstate->stage][stage_idx] =
@@ -2965,10 +2966,18 @@ static void sde_crtc_atomic_flush(struct drm_crtc *crtc,
	 * required. However, if those planes were power collapsed since
	 * last commit cycle, driver has to restore the hardware state
	 * of those planes explicitly here prior to plane flush.
	 * Also use this iteration to see if any plane requires cache,
	 * so during the perf update driver can activate/deactivate
	 * the cache accordingly.
	 */
	drm_atomic_crtc_for_each_plane(plane, crtc)
	sde_crtc->new_perf.llcc_active = false;
	drm_atomic_crtc_for_each_plane(plane, crtc) {
		sde_plane_restore(plane);

		if (sde_plane_is_cache_required(plane))
			sde_crtc->new_perf.llcc_active = true;
	}

	/* wait for acquire fences before anything else is done */
	_sde_crtc_wait_for_fences(crtc);

@@ -5737,9 +5746,17 @@ struct drm_crtc *sde_crtc_init(struct drm_device *dev, struct drm_plane *plane)
	sde_cp_crtc_init(crtc);
	sde_cp_crtc_install_properties(crtc);

	sde_crtc->cur_perf.llcc_active = false;
	sde_crtc->new_perf.llcc_active = false;

	kthread_init_delayed_work(&sde_crtc->idle_notify_work,
					__sde_crtc_idle_notify_work);

	SDE_DEBUG("crtc=%d new_llcc=%d, old_llcc=%d\n",
		crtc->base.id,
		sde_crtc->new_perf.llcc_active,
		sde_crtc->cur_perf.llcc_active);

	SDE_DEBUG("%s: successfully initialized crtc\n", sde_crtc->name);
	return crtc;
}
+45 −0
Original line number Diff line number Diff line
@@ -642,6 +642,16 @@ static const struct sde_format sde_format_map_tp10_ubwc[] = {
		SDE_FETCH_UBWC, 4, SDE_TILE_HEIGHT_NV12),
};

inline bool sde_format_is_tp10_ubwc(const struct sde_format *fmt)
{
	if (SDE_FORMAT_IS_YUV(fmt) && SDE_FORMAT_IS_DX(fmt) &&
			SDE_FORMAT_IS_UBWC(fmt) &&
			(fmt->num_planes == 4) && fmt->unpack_tight)
		return true;
	else
		return false;
}

/* _sde_get_v_h_subsample_rate - Get subsample rates for all formats we support
 *   Note: Not using the drm_format_*_subsampling since we have formats
 */
@@ -1334,3 +1344,38 @@ uint32_t sde_populate_formats(

	return i;
}

int sde_format_validate_fmt(struct msm_kms *kms,
	const struct msm_format *msm_fmt,
	const struct sde_format_extended *fmt_list)
{
	const struct msm_format *fmt_tmp;
	bool valid_format = false;
	int ret = 0;

	if (!msm_fmt || !fmt_list) {
		SDE_ERROR("invalid fmt:%d list:%d\n",
			!msm_fmt, !fmt_list);
		ret = -EINVAL;
		goto exit;
	}

	while (fmt_list->fourcc_format) {
		fmt_tmp = sde_get_msm_format(kms,
				fmt_list->fourcc_format,
				fmt_list->modifier);
		if (fmt_tmp &&
			(fmt_tmp->pixel_format == msm_fmt->pixel_format)) {
			valid_format = true;
			break;
		}
		++fmt_list;
	}

	if (!valid_format) {
		SDE_ERROR("fmt:%d not found within the list!\n", *msm_fmt);
		ret = -EINVAL;
	}
exit:
	return ret;
}
+21 −0
Original line number Diff line number Diff line
@@ -142,4 +142,25 @@ uint32_t sde_format_get_framebuffer_size(
		const uint32_t *pitches,
		const uint64_t modifier);

/**
 * sde_format_is_tp10_ubwc - check if the format is tp10 ubwc
 * @format:            DRM pixel format
 *
 * Return: returns true if the format is tp10 ubwc, otherwise false.
 */
inline bool sde_format_is_tp10_ubwc(const struct sde_format *fmt);

/**
 * sde_format_validate_fmt - validates if the format "msm_fmt" is within
 *	the list "fmt_list"
 * @kms: pointer to the kms object
 * @msm_fmt: pointer to the format to look within the list
 * @fmt_list: list where driver will loop to look for the 'msm_fmt' format.
 * @result: returns 0 if the format is found, otherwise will return an
 *	error code.
 */
int sde_format_validate_fmt(struct msm_kms *kms,
	const struct msm_format *msm_fmt,
	const struct sde_format_extended *fmt_list);

#endif /*_SDE_FORMATS_H */
Loading