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

Commit d34ef7dc authored by RAJAT GUPTA's avatar RAJAT GUPTA Committed by Xiaowen Wu
Browse files

drm/msm: update topology based on clock requirement



Update the topology allocation by considering the required
mode clock (vtotal x htotal x fps * fudge factor). Modes with
a clock that exceeds the maximum SDE clock will be denoted as
requiring a topology that uses two layer mixers.

Change-Id: I3c773598b0d79cb6fea9d3a0e04d89ff84d67e13
Signed-off-by: default avatarRAJAT GUPTA <rajatgu@codeaurora.org>
parent 4e4f2e80
Loading
Loading
Loading
Loading
+11 −4
Original line number Diff line number Diff line
@@ -367,8 +367,6 @@ int dp_connector_get_mode_info(struct drm_connector *connector,
		struct msm_mode_info *mode_info,
		u32 max_mixer_width, void *display)
{
	const u32 dual_lm = 2;
	const u32 single_lm = 1;
	const u32 single_intf = 1;
	const u32 no_enc = 0;
	struct msm_display_topology *topology;
@@ -376,6 +374,8 @@ int dp_connector_get_mode_info(struct drm_connector *connector,
	struct dp_panel *dp_panel;
	struct dp_display_mode dp_mode;
	struct dp_display *dp_disp = display;
	struct msm_drm_private *priv;
	int rc = 0;

	if (!drm_mode || !mode_info || !max_mixer_width || !connector ||
			!display) {
@@ -387,10 +387,17 @@ int dp_connector_get_mode_info(struct drm_connector *connector,

	sde_conn = to_sde_connector(connector);
	dp_panel = sde_conn->drv_panel;
	priv = connector->dev->dev_private;

	topology = &mode_info->topology;
	topology->num_lm = (max_mixer_width < drm_mode->hdisplay) ?
							dual_lm : single_lm;

	rc = msm_get_mixer_count(priv, drm_mode, max_mixer_width,
			&topology->num_lm);
	if (rc) {
		pr_err("error getting mixer count, rc:%d\n", rc);
		return rc;
	}

	topology->num_enc = no_enc;
	topology->num_intf = single_intf;

+27 −0
Original line number Diff line number Diff line
@@ -1978,6 +1978,33 @@ msm_gem_smmu_address_space_get(struct drm_device *dev,
	return funcs->get_address_space(priv->kms, domain);
}

int msm_get_mixer_count(struct msm_drm_private *priv,
		const struct drm_display_mode *mode,
		u32 max_mixer_width, u32 *num_lm)
{
	struct msm_kms *kms;
	const struct msm_kms_funcs *funcs;

	if (!priv) {
		DRM_ERROR("invalid drm private struct");
		return -EINVAL;
	}

	kms = priv->kms;
	if (!kms) {
		DRM_ERROR("invalid msm kms struct");
		return -EINVAL;
	}

	funcs = kms->funcs;
	if (!funcs || !funcs->get_mixer_count) {
		DRM_ERROR("invlaid function pointers");
		return -EINVAL;
	}

	return funcs->get_mixer_count(priv->kms, mode,
			max_mixer_width, num_lm);
}
/*
 * We don't know what's the best binding to link the gpu with the drm device.
 * Fow now, we just hunt for all the possible gpus that we support, and add them
+3 −0
Original line number Diff line number Diff line
@@ -986,4 +986,7 @@ static inline unsigned long timeout_to_jiffies(const ktime_t *timeout)
	return remaining_jiffies;
}

int msm_get_mixer_count(struct msm_drm_private *priv,
		const struct drm_display_mode *mode,
		u32 max_mixer_width, u32 *num_lm);
#endif /* __MSM_DRV_H__ */
+4 −0
Original line number Diff line number Diff line
@@ -119,6 +119,10 @@ struct msm_kms_funcs {
	int (*cont_splash_config)(struct msm_kms *kms);
	/* check for continuous splash status */
	bool (*check_for_splash)(struct msm_kms *kms);
	/* topology information */
	int (*get_mixer_count)(const struct msm_kms *kms,
			const struct drm_display_mode *mode,
			u32 mode_max_width, u32 *num_lm);
};

struct msm_kms {
+49 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#define pr_fmt(fmt)	"[drm:%s:%d] " fmt, __func__, __LINE__

#include <drm/drm_crtc.h>
#include <drm/drm_fixed.h>
#include <linux/debugfs.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
@@ -2653,6 +2654,53 @@ static bool sde_kms_check_for_splash(struct msm_kms *kms)
	return sde_kms->splash_data.num_splash_displays;
}

static int sde_kms_get_mixer_count(const struct msm_kms *kms,
		const struct drm_display_mode *mode,
		u32 max_mixer_width, u32 *num_lm)
{
	struct sde_kms *sde_kms;
	s64 mode_clock_hz = 0;
	s64 max_mdp_clock_hz = 0;
	s64 mdp_fudge_factor = 0;
	s64 temp = 0;
	s64 htotal_fp = 0;
	s64 vtotal_fp = 0;
	s64 vrefresh_fp = 0;

	if (!num_lm) {
		SDE_ERROR("invalid num_lm pointer\n");
		return -EINVAL;
	}
	*num_lm = 1;

	if (!kms || !mode || !max_mixer_width) {
		SDE_ERROR("invlaid input args");
		return -EINVAL;
	}

	sde_kms = to_sde_kms(kms);

	max_mdp_clock_hz = drm_fixp_from_fraction(
			sde_kms->perf.max_core_clk_rate, 1);
	mdp_fudge_factor = drm_fixp_from_fraction(105, 100);
	htotal_fp = drm_fixp_from_fraction(mode->htotal, 1);
	vtotal_fp =  drm_fixp_from_fraction(mode->vtotal, 1);
	vrefresh_fp =  drm_fixp_from_fraction(mode->vrefresh, 1);

	temp = drm_fixp_mul(htotal_fp, vtotal_fp);
	temp = drm_fixp_mul(temp, vrefresh_fp);
	mode_clock_hz = drm_fixp_mul(temp, mdp_fudge_factor);

	if (mode_clock_hz > max_mdp_clock_hz ||
			mode->hdisplay > max_mixer_width)
		*num_lm = 2;

	SDE_DEBUG("[%s] h=%d, v=%d, fps%d, max_mdp_pclk_hz=%llu, num_lm=%d\n",
			mode->name, mode->htotal, mode->vtotal, mode->vrefresh,
			sde_kms->perf.max_core_clk_rate, *num_lm);
	return 0;
}

static void _sde_kms_null_commit(struct drm_device *dev,
		struct drm_encoder *enc)
{
@@ -2961,6 +3009,7 @@ static const struct msm_kms_funcs kms_funcs = {
	.get_address_space = _sde_kms_get_address_space,
	.postopen = _sde_kms_post_open,
	.check_for_splash = sde_kms_check_for_splash,
	.get_mixer_count = sde_kms_get_mixer_count,
};

/* the caller api needs to turn on clock before calling it */