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

Commit 2edd6443 authored by Ander Conselvan de Oliveira's avatar Ander Conselvan de Oliveira
Browse files

drm/i915: Use a table to initilize shared dplls



Use a table to store the per-platform shared dpll information in one
place. This way, there is no need for platform specific init funtions.

Signed-off-by: default avatarAnder Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
Reviewed-by: default avatarMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1457451987-17466-8-git-send-email-ander.conselvan.de.oliveira@intel.com
parent c2a9fcd6
Loading
Loading
Loading
Loading
+8 −8
Original line number Original line Diff line number Diff line
@@ -9309,7 +9309,7 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
			intel_get_shared_dpll_by_id(dev_priv, pll_id);
			intel_get_shared_dpll_by_id(dev_priv, pll_id);
		pll = pipe_config->shared_dpll;
		pll = pipe_config->shared_dpll;


		WARN_ON(!pll->get_hw_state(dev_priv, pll,
		WARN_ON(!pll->funcs.get_hw_state(dev_priv, pll,
						 &pipe_config->dpll_hw_state));
						 &pipe_config->dpll_hw_state));


		tmp = pipe_config->dpll_hw_state.dpll;
		tmp = pipe_config->dpll_hw_state.dpll;
@@ -9856,7 +9856,7 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc,


	pll = pipe_config->shared_dpll;
	pll = pipe_config->shared_dpll;
	if (pll) {
	if (pll) {
		WARN_ON(!pll->get_hw_state(dev_priv, pll,
		WARN_ON(!pll->funcs.get_hw_state(dev_priv, pll,
						 &pipe_config->dpll_hw_state));
						 &pipe_config->dpll_hw_state));
	}
	}


@@ -12935,7 +12935,7 @@ check_shared_dpll_state(struct drm_device *dev)


		DRM_DEBUG_KMS("%s\n", pll->name);
		DRM_DEBUG_KMS("%s\n", pll->name);


		active = pll->get_hw_state(dev_priv, pll, &dpll_hw_state);
		active = pll->funcs.get_hw_state(dev_priv, pll, &dpll_hw_state);


		I915_STATE_WARN(pll->active > hweight32(pll->config.crtc_mask),
		I915_STATE_WARN(pll->active > hweight32(pll->config.crtc_mask),
		     "more active pll users than references: %i vs %i\n",
		     "more active pll users than references: %i vs %i\n",
@@ -15686,7 +15686,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
	for (i = 0; i < dev_priv->num_shared_dpll; i++) {
	for (i = 0; i < dev_priv->num_shared_dpll; i++) {
		struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
		struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];


		pll->on = pll->get_hw_state(dev_priv, pll,
		pll->on = pll->funcs.get_hw_state(dev_priv, pll,
						  &pll->config.hw_state);
						  &pll->config.hw_state);
		pll->active = 0;
		pll->active = 0;
		pll->config.crtc_mask = 0;
		pll->config.crtc_mask = 0;
@@ -15824,7 +15824,7 @@ intel_modeset_setup_hw_state(struct drm_device *dev)


		DRM_DEBUG_KMS("%s enabled but not in use, disabling\n", pll->name);
		DRM_DEBUG_KMS("%s enabled but not in use, disabling\n", pll->name);


		pll->disable(dev_priv, pll);
		pll->funcs.disable(dev_priv, pll);
		pll->on = false;
		pll->on = false;
	}
	}


+86 −103
Original line number Original line Diff line number Diff line
@@ -74,7 +74,7 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv,
	if (WARN(!pll, "asserting DPLL %s with no DPLL\n", onoff(state)))
	if (WARN(!pll, "asserting DPLL %s with no DPLL\n", onoff(state)))
		return;
		return;


	cur_state = pll->get_hw_state(dev_priv, pll, &hw_state);
	cur_state = pll->funcs.get_hw_state(dev_priv, pll, &hw_state);
	I915_STATE_WARN(cur_state != state,
	I915_STATE_WARN(cur_state != state,
	     "%s assertion failure (expected %s, current %s)\n",
	     "%s assertion failure (expected %s, current %s)\n",
			pll->name, onoff(state), onoff(cur_state));
			pll->name, onoff(state), onoff(cur_state));
@@ -95,7 +95,7 @@ void intel_prepare_shared_dpll(struct intel_crtc *crtc)
		WARN_ON(pll->on);
		WARN_ON(pll->on);
		assert_shared_dpll_disabled(dev_priv, pll);
		assert_shared_dpll_disabled(dev_priv, pll);


		pll->mode_set(dev_priv, pll);
		pll->funcs.mode_set(dev_priv, pll);
	}
	}
}
}


@@ -133,7 +133,7 @@ void intel_enable_shared_dpll(struct intel_crtc *crtc)
	intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS);
	intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS);


	DRM_DEBUG_KMS("enabling %s\n", pll->name);
	DRM_DEBUG_KMS("enabling %s\n", pll->name);
	pll->enable(dev_priv, pll);
	pll->funcs.enable(dev_priv, pll);
	pll->on = true;
	pll->on = true;
}
}


@@ -168,7 +168,7 @@ void intel_disable_shared_dpll(struct intel_crtc *crtc)
		return;
		return;


	DRM_DEBUG_KMS("disabling %s\n", pll->name);
	DRM_DEBUG_KMS("disabling %s\n", pll->name);
	pll->disable(dev_priv, pll);
	pll->funcs.disable(dev_priv, pll);
	pll->on = false;
	pll->on = false;


	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
@@ -398,29 +398,13 @@ static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv,
	udelay(200);
	udelay(200);
}
}


static char *ibx_pch_dpll_names[] = {
static const struct intel_shared_dpll_funcs ibx_pch_dpll_funcs = {
	"PCH DPLL A",
	.mode_set = ibx_pch_dpll_mode_set,
	"PCH DPLL B",
	.enable = ibx_pch_dpll_enable,
	.disable = ibx_pch_dpll_disable,
	.get_hw_state = ibx_pch_dpll_get_hw_state,
};
};


static void ibx_pch_dpll_init(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	int i;

	dev_priv->num_shared_dpll = 2;

	for (i = 0; i < dev_priv->num_shared_dpll; i++) {
		dev_priv->shared_dplls[i].id = i;
		dev_priv->shared_dplls[i].name = ibx_pch_dpll_names[i];
		dev_priv->shared_dplls[i].mode_set = ibx_pch_dpll_mode_set;
		dev_priv->shared_dplls[i].enable = ibx_pch_dpll_enable;
		dev_priv->shared_dplls[i].disable = ibx_pch_dpll_disable;
		dev_priv->shared_dplls[i].get_hw_state =
			ibx_pch_dpll_get_hw_state;
	}
}

static void hsw_ddi_wrpll_enable(struct drm_i915_private *dev_priv,
static void hsw_ddi_wrpll_enable(struct drm_i915_private *dev_priv,
			       struct intel_shared_dpll *pll)
			       struct intel_shared_dpll *pll)
{
{
@@ -492,40 +476,16 @@ static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv,
}
}




static const char * const hsw_ddi_pll_names[] = {
static const struct intel_shared_dpll_funcs hsw_ddi_wrpll_funcs = {
	"WRPLL 1",
	.enable = hsw_ddi_wrpll_enable,
	"WRPLL 2",
	.disable = hsw_ddi_wrpll_disable,
	"SPLL"
	.get_hw_state = hsw_ddi_wrpll_get_hw_state,
};
};


static void hsw_shared_dplls_init(struct drm_i915_private *dev_priv)
static const struct intel_shared_dpll_funcs hsw_ddi_spll_funcs = {
{
	.enable = hsw_ddi_spll_enable,
	int i;
	.disable = hsw_ddi_spll_disable,

	.get_hw_state = hsw_ddi_spll_get_hw_state,
	dev_priv->num_shared_dpll = 3;

	for (i = 0; i < 2; i++) {
		dev_priv->shared_dplls[i].id = i;
		dev_priv->shared_dplls[i].name = hsw_ddi_pll_names[i];
		dev_priv->shared_dplls[i].disable = hsw_ddi_wrpll_disable;
		dev_priv->shared_dplls[i].enable = hsw_ddi_wrpll_enable;
		dev_priv->shared_dplls[i].get_hw_state =
			hsw_ddi_wrpll_get_hw_state;
	}

	/* SPLL is special, but needs to be initialized anyway.. */
	dev_priv->shared_dplls[i].id = i;
	dev_priv->shared_dplls[i].name = hsw_ddi_pll_names[i];
	dev_priv->shared_dplls[i].disable = hsw_ddi_spll_disable;
	dev_priv->shared_dplls[i].enable = hsw_ddi_spll_enable;
	dev_priv->shared_dplls[i].get_hw_state = hsw_ddi_spll_get_hw_state;

}

static const char * const skl_ddi_pll_names[] = {
	"DPLL 1",
	"DPLL 2",
	"DPLL 3",
};
};


struct skl_dpll_regs {
struct skl_dpll_regs {
@@ -634,26 +594,10 @@ static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
	return ret;
	return ret;
}
}


static void skl_shared_dplls_init(struct drm_i915_private *dev_priv)
static const struct intel_shared_dpll_funcs skl_ddi_pll_funcs = {
{
	.enable = skl_ddi_pll_enable,
	int i;
	.disable = skl_ddi_pll_disable,

	.get_hw_state = skl_ddi_pll_get_hw_state,
	dev_priv->num_shared_dpll = 3;

	for (i = 0; i < dev_priv->num_shared_dpll; i++) {
		dev_priv->shared_dplls[i].id = i;
		dev_priv->shared_dplls[i].name = skl_ddi_pll_names[i];
		dev_priv->shared_dplls[i].disable = skl_ddi_pll_disable;
		dev_priv->shared_dplls[i].enable = skl_ddi_pll_enable;
		dev_priv->shared_dplls[i].get_hw_state =
			skl_ddi_pll_get_hw_state;
	}
}

static const char * const bxt_ddi_pll_names[] = {
	"PORT PLL A",
	"PORT PLL B",
	"PORT PLL C",
};
};


static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv,
static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv,
@@ -838,34 +782,17 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
	return ret;
	return ret;
}
}


static void bxt_shared_dplls_init(struct drm_i915_private *dev_priv)
static const struct intel_shared_dpll_funcs bxt_ddi_pll_funcs = {
{
	.enable = bxt_ddi_pll_enable,
	int i;
	.disable = bxt_ddi_pll_disable,

	.get_hw_state = bxt_ddi_pll_get_hw_state,
	dev_priv->num_shared_dpll = 3;
};

	for (i = 0; i < dev_priv->num_shared_dpll; i++) {
		dev_priv->shared_dplls[i].id = i;
		dev_priv->shared_dplls[i].name = bxt_ddi_pll_names[i];
		dev_priv->shared_dplls[i].disable = bxt_ddi_pll_disable;
		dev_priv->shared_dplls[i].enable = bxt_ddi_pll_enable;
		dev_priv->shared_dplls[i].get_hw_state =
			bxt_ddi_pll_get_hw_state;
	}
}


static void intel_ddi_pll_init(struct drm_device *dev)
static void intel_ddi_pll_init(struct drm_device *dev)
{
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct drm_i915_private *dev_priv = dev->dev_private;
	uint32_t val = I915_READ(LCPLL_CTL);
	uint32_t val = I915_READ(LCPLL_CTL);


	if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
		skl_shared_dplls_init(dev_priv);
	else if (IS_BROXTON(dev))
		bxt_shared_dplls_init(dev_priv);
	else
		hsw_shared_dplls_init(dev_priv);

	if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
	if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
		int cdclk_freq;
		int cdclk_freq;


@@ -893,16 +820,72 @@ static void intel_ddi_pll_init(struct drm_device *dev)
	}
	}
}
}


struct dpll_info {
	const char *name;
	const int id;
	const struct intel_shared_dpll_funcs *funcs;
};

static const struct dpll_info pch_plls[] = {
	{ "PCH DPLL A", DPLL_ID_PCH_PLL_A, &ibx_pch_dpll_funcs },
	{ "PCH DPLL B", DPLL_ID_PCH_PLL_B, &ibx_pch_dpll_funcs },
	{ NULL, -1, NULL },
};

static const struct dpll_info hsw_plls[] = {
	{ "WRPLL 1", DPLL_ID_WRPLL1, &hsw_ddi_wrpll_funcs },
	{ "WRPLL 2", DPLL_ID_WRPLL2, &hsw_ddi_wrpll_funcs },
	{ "SPLL",    DPLL_ID_SPLL,   &hsw_ddi_spll_funcs },
	{ NULL, -1, NULL, },
};

static const struct dpll_info skl_plls[] = {
	{ "DPPL 1", DPLL_ID_SKL_DPLL1, &skl_ddi_pll_funcs },
	{ "DPPL 2", DPLL_ID_SKL_DPLL2, &skl_ddi_pll_funcs },
	{ "DPPL 3", DPLL_ID_SKL_DPLL3, &skl_ddi_pll_funcs },
	{ NULL, -1, NULL, },
};

static const struct dpll_info bxt_plls[] = {
	{ "PORT PLL A", 0, &bxt_ddi_pll_funcs },
	{ "PORT PLL B", 1, &bxt_ddi_pll_funcs },
	{ "PORT PLL C", 2, &bxt_ddi_pll_funcs },
	{ NULL, -1, NULL, },
};

void intel_shared_dpll_init(struct drm_device *dev)
void intel_shared_dpll_init(struct drm_device *dev)
{
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct drm_i915_private *dev_priv = dev->dev_private;
	const struct dpll_info *dpll_info = NULL;
	int i;


	if (HAS_DDI(dev))
	if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
		intel_ddi_pll_init(dev);
		dpll_info = skl_plls;
	else if IS_BROXTON(dev)
		dpll_info = bxt_plls;
	else if (HAS_DDI(dev))
		dpll_info = hsw_plls;
	else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
	else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
		ibx_pch_dpll_init(dev);
		dpll_info = pch_plls;
	else

	if (!dpll_info) {
		dev_priv->num_shared_dpll = 0;
		dev_priv->num_shared_dpll = 0;
		return;
	}

	for (i = 0; dpll_info[i].id >= 0; i++) {
		WARN_ON(i != dpll_info[i].id);

		dev_priv->shared_dplls[i].id = dpll_info[i].id;
		dev_priv->shared_dplls[i].name = dpll_info[i].name;
		dev_priv->shared_dplls[i].funcs = *dpll_info[i].funcs;
	}

	dev_priv->num_shared_dpll = i;


	BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS);
	BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS);

	/* FIXME: Move this to a more suitable place */
	if (HAS_DDI(dev))
		intel_ddi_pll_init(dev);
}
}
+14 −8
Original line number Original line Diff line number Diff line
@@ -28,6 +28,7 @@
struct drm_i915_private;
struct drm_i915_private;
struct intel_crtc;
struct intel_crtc;
struct intel_crtc_state;
struct intel_crtc_state;
struct intel_shared_dpll;


enum intel_dpll_id {
enum intel_dpll_id {
	DPLL_ID_PRIVATE = -1, /* non-shared dpll in use */
	DPLL_ID_PRIVATE = -1, /* non-shared dpll in use */
@@ -78,14 +79,7 @@ struct intel_shared_dpll_config {
	struct intel_dpll_hw_state hw_state;
	struct intel_dpll_hw_state hw_state;
};
};


struct intel_shared_dpll {
struct intel_shared_dpll_funcs {
	struct intel_shared_dpll_config config;

	int active; /* count of number of active CRTCs (i.e. DPMS on) */
	bool on; /* is the PLL actually active? Disabled during modeset */
	const char *name;
	/* should match the index in the dev_priv->shared_dplls array */
	enum intel_dpll_id id;
	/* The mode_set hook is optional and should be used together with the
	/* The mode_set hook is optional and should be used together with the
	 * intel_prepare_shared_dpll function. */
	 * intel_prepare_shared_dpll function. */
	void (*mode_set)(struct drm_i915_private *dev_priv,
	void (*mode_set)(struct drm_i915_private *dev_priv,
@@ -99,6 +93,18 @@ struct intel_shared_dpll {
			     struct intel_dpll_hw_state *hw_state);
			     struct intel_dpll_hw_state *hw_state);
};
};


struct intel_shared_dpll {
	struct intel_shared_dpll_config config;

	int active; /* count of number of active CRTCs (i.e. DPMS on) */
	bool on; /* is the PLL actually active? Disabled during modeset */
	const char *name;
	/* should match the index in the dev_priv->shared_dplls array */
	enum intel_dpll_id id;

	struct intel_shared_dpll_funcs funcs;
};

#define SKL_DPLL0 0
#define SKL_DPLL0 0
#define SKL_DPLL1 1
#define SKL_DPLL1 1
#define SKL_DPLL2 2
#define SKL_DPLL2 2