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

Commit 9d16da65 authored by Ander Conselvan de Oliveira's avatar Ander Conselvan de Oliveira
Browse files

drm/i915: Manage HSW/BDW LCPLLs with the shared dpll interface



Manage the LCPLLs used with DisplayPort, so that all the HSW/BDW DPLLs
are managed by the shared dpll code.

v2: Introduce INTEL_DPLL_ALWAYS_ON flag to please state checker. (Ander)

v3: Initialize pll->flags in intel_shared_dpll_init(). (Ander)

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-13-git-send-email-ander.conselvan.de.oliveira@intel.com
parent 34177c24
Loading
Loading
Loading
Loading
+7 −11
Original line number Diff line number Diff line
@@ -992,17 +992,13 @@ hsw_ddi_pll_select(struct intel_crtc *intel_crtc,
{
	struct intel_shared_dpll *pll;

	if (intel_encoder->type == INTEL_OUTPUT_HDMI ||
	    intel_encoder->type == INTEL_OUTPUT_ANALOG) {
	pll = intel_get_shared_dpll(intel_crtc, crtc_state,
				    intel_encoder);
	if (!pll)
		DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
				 pipe_name(intel_crtc->pipe));

	return pll;
	} else {
		return true;
	}
}

static bool
+17 −8
Original line number Diff line number Diff line
@@ -9821,13 +9821,19 @@ static void haswell_get_ddi_pll(struct drm_i915_private *dev_priv,
	case PORT_CLK_SEL_SPLL:
		id = DPLL_ID_SPLL;
		break;
	case PORT_CLK_SEL_LCPLL_810:
		id = DPLL_ID_LCPLL_810;
		break;
	case PORT_CLK_SEL_LCPLL_1350:
		id = DPLL_ID_LCPLL_1350;
		break;
	case PORT_CLK_SEL_LCPLL_2700:
		id = DPLL_ID_LCPLL_2700;
		break;
	default:
		MISSING_CASE(pipe_config->ddi_pll_sel);
		/* fall through */
	case PORT_CLK_SEL_NONE:
	case PORT_CLK_SEL_LCPLL_810:
	case PORT_CLK_SEL_LCPLL_1350:
	case PORT_CLK_SEL_LCPLL_2700:
		return;
	}

@@ -12942,11 +12948,14 @@ check_shared_dpll_state(struct drm_device *dev)
		     pll->active, hweight32(pll->config.crtc_mask));
		I915_STATE_WARN(pll->active && !pll->on,
		     "pll in active use but not on in sw tracking\n");

		if (!(pll->flags & INTEL_DPLL_ALWAYS_ON)) {
			I915_STATE_WARN(pll->on && !pll->active,
			     "pll in on but not on in use in sw tracking\n");
			I915_STATE_WARN(pll->on != active,
			     "pll on state mismatch (expected %i, found %i)\n",
			     pll->on, active);
		}

		for_each_intel_crtc(dev, crtc) {
			if (crtc->base.state->enable && crtc->config->shared_dpll == pll)
+1 −22
Original line number Diff line number Diff line
@@ -1283,25 +1283,6 @@ skl_edp_set_pll_config(struct intel_crtc_state *pipe_config)
	pipe_config->dpll_hw_state.ctrl1 = ctrl1;
}

void
hsw_dp_set_ddi_pll_sel(struct intel_crtc_state *pipe_config)
{
	memset(&pipe_config->dpll_hw_state, 0,
	       sizeof(pipe_config->dpll_hw_state));

	switch (pipe_config->port_clock / 2) {
	case 81000:
		pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_810;
		break;
	case 135000:
		pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_1350;
		break;
	case 270000:
		pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_2700;
		break;
	}
}

static int
intel_dp_sink_rates(struct intel_dp *intel_dp, const int **sink_rates)
{
@@ -1661,10 +1642,8 @@ intel_dp_compute_config(struct intel_encoder *encoder,

	if ((IS_SKYLAKE(dev)  || IS_KABYLAKE(dev)) && is_edp(intel_dp))
		skl_edp_set_pll_config(pipe_config);
	else if (IS_BROXTON(dev))
	else if (IS_BROXTON(dev) || IS_HASWELL(dev) || IS_BROADWELL(dev))
		/* handled in ddi */;
	else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
		hsw_dp_set_ddi_pll_sel(pipe_config);
	else
		intel_dp_set_clock(encoder, pipe_config);

+0 −4
Original line number Diff line number Diff line
@@ -33,7 +33,6 @@
static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
					struct intel_crtc_state *pipe_config)
{
	struct drm_device *dev = encoder->base.dev;
	struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
	struct intel_digital_port *intel_dig_port = intel_mst->primary;
	struct intel_dp *intel_dp = &intel_dig_port->dp;
@@ -92,9 +91,6 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,

	pipe_config->dp_m_n.tu = slots;

	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
		hsw_dp_set_ddi_pll_sel(pipe_config);

	return true;

}
+72 −18
Original line number Diff line number Diff line
@@ -447,6 +447,12 @@ static uint32_t hsw_pll_to_ddi_pll_sel(struct intel_shared_dpll *pll)
		return PORT_CLK_SEL_WRPLL2;
	case DPLL_ID_SPLL:
		return PORT_CLK_SEL_SPLL;
	case DPLL_ID_LCPLL_810:
		return PORT_CLK_SEL_LCPLL_810;
	case DPLL_ID_LCPLL_1350:
		return PORT_CLK_SEL_LCPLL_1350;
	case DPLL_ID_LCPLL_2700:
		return PORT_CLK_SEL_LCPLL_2700;
	default:
		return PORT_CLK_SEL_NONE;
	}
@@ -671,9 +677,13 @@ static struct intel_shared_dpll *
hsw_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
	     struct intel_encoder *encoder)
{
	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
	struct intel_shared_dpll *pll;
	int clock = crtc_state->port_clock;

	memset(&crtc_state->dpll_hw_state, 0,
	       sizeof(crtc_state->dpll_hw_state));

	if (encoder->type == INTEL_OUTPUT_HDMI) {
		uint32_t val;
		unsigned p, n2, r2;
@@ -684,21 +694,37 @@ hsw_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
		      WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
		      WRPLL_DIVIDER_POST(p);

		memset(&crtc_state->dpll_hw_state, 0,
		       sizeof(crtc_state->dpll_hw_state));

		crtc_state->dpll_hw_state.wrpll = val;

		pll = intel_find_shared_dpll(crtc, crtc_state,
					     DPLL_ID_WRPLL1, DPLL_ID_WRPLL2);

	} else if (encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
		   encoder->type == INTEL_OUTPUT_DP_MST ||
		   encoder->type == INTEL_OUTPUT_EDP) {
		enum intel_dpll_id pll_id;

		switch (clock / 2) {
		case 81000:
			pll_id = DPLL_ID_LCPLL_810;
			break;
		case 135000:
			pll_id = DPLL_ID_LCPLL_1350;
			break;
		case 270000:
			pll_id = DPLL_ID_LCPLL_2700;
			break;
		default:
			DRM_DEBUG_KMS("Invalid clock for DP: %d\n", clock);
			return NULL;
		}

		pll = intel_get_shared_dpll_by_id(dev_priv, pll_id);

	} else if (encoder->type == INTEL_OUTPUT_ANALOG) {
		if (WARN_ON(crtc_state->port_clock / 2 != 135000))
			return NULL;

		memset(&crtc_state->dpll_hw_state, 0,
		       sizeof(crtc_state->dpll_hw_state));

		crtc_state->dpll_hw_state.spll =
			SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC;

@@ -731,6 +757,29 @@ static const struct intel_shared_dpll_funcs hsw_ddi_spll_funcs = {
	.get_hw_state = hsw_ddi_spll_get_hw_state,
};

static void hsw_ddi_lcpll_enable(struct drm_i915_private *dev_priv,
				 struct intel_shared_dpll *pll)
{
}

static void hsw_ddi_lcpll_disable(struct drm_i915_private *dev_priv,
				  struct intel_shared_dpll *pll)
{
}

static bool hsw_ddi_lcpll_get_hw_state(struct drm_i915_private *dev_priv,
				       struct intel_shared_dpll *pll,
				       struct intel_dpll_hw_state *hw_state)
{
	return true;
}

static const struct intel_shared_dpll_funcs hsw_ddi_lcpll_funcs = {
	.enable = hsw_ddi_lcpll_enable,
	.disable = hsw_ddi_lcpll_disable,
	.get_hw_state = hsw_ddi_lcpll_get_hw_state,
};

struct skl_dpll_regs {
	i915_reg_t ctl, cfgcr1, cfgcr2;
};
@@ -1537,6 +1586,7 @@ struct dpll_info {
	const char *name;
	const int id;
	const struct intel_shared_dpll_funcs *funcs;
	uint32_t flags;
};

struct intel_dpll_mgr {
@@ -1548,9 +1598,9 @@ struct intel_dpll_mgr {
};

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 },
	{ "PCH DPLL A", DPLL_ID_PCH_PLL_A, &ibx_pch_dpll_funcs, 0 },
	{ "PCH DPLL B", DPLL_ID_PCH_PLL_B, &ibx_pch_dpll_funcs, 0 },
	{ NULL, -1, NULL, 0 },
};

static const struct intel_dpll_mgr pch_pll_mgr = {
@@ -1559,9 +1609,12 @@ static const struct intel_dpll_mgr pch_pll_mgr = {
};

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 },
	{ "WRPLL 1",    DPLL_ID_WRPLL1,     &hsw_ddi_wrpll_funcs, 0 },
	{ "WRPLL 2",    DPLL_ID_WRPLL2,     &hsw_ddi_wrpll_funcs, 0 },
	{ "SPLL",       DPLL_ID_SPLL,       &hsw_ddi_spll_funcs,  0 },
	{ "LCPLL 810",  DPLL_ID_LCPLL_810,  &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
	{ "LCPLL 1350", DPLL_ID_LCPLL_1350, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
	{ "LCPLL 2700", DPLL_ID_LCPLL_2700, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
	{ NULL, -1, NULL, },
};

@@ -1571,9 +1624,9 @@ static const struct intel_dpll_mgr hsw_pll_mgr = {
};

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 },
	{ "DPPL 1", DPLL_ID_SKL_DPLL1, &skl_ddi_pll_funcs, 0 },
	{ "DPPL 2", DPLL_ID_SKL_DPLL2, &skl_ddi_pll_funcs, 0 },
	{ "DPPL 3", DPLL_ID_SKL_DPLL3, &skl_ddi_pll_funcs, 0 },
	{ NULL, -1, NULL, },
};

@@ -1583,9 +1636,9 @@ static const struct intel_dpll_mgr skl_pll_mgr = {
};

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 },
	{ "PORT PLL A", 0, &bxt_ddi_pll_funcs, 0 },
	{ "PORT PLL B", 1, &bxt_ddi_pll_funcs, 0 },
	{ "PORT PLL C", 2, &bxt_ddi_pll_funcs, 0 },
	{ NULL, -1, NULL, },
};

@@ -1623,6 +1676,7 @@ void intel_shared_dpll_init(struct drm_device *dev)
		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->shared_dplls[i].flags = dpll_info[i].flags;
	}

	dev_priv->dpll_mgr = dpll_mgr;
Loading