Exemplo n.º 1
0
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;

		hsw_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);

		val = WRPLL_PLL_ENABLE | WRPLL_PLL_LCPLL |
		      WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
		      WRPLL_DIVIDER_POST(p);

		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;

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

		pll = intel_find_shared_dpll(crtc, crtc_state,
					     DPLL_ID_SPLL, DPLL_ID_SPLL);
	} else {
		return NULL;
	}

	if (!pll)
		return NULL;

	crtc_state->ddi_pll_sel = hsw_pll_to_ddi_pll_sel(pll);

	intel_reference_shared_dpll(pll, crtc_state);

	return pll;
}
Exemplo n.º 2
0
void intel_ddi_mode_set(struct drm_encoder *encoder,
				struct drm_display_mode *mode,
				struct drm_display_mode *adjusted_mode)
{
	struct drm_device *dev = encoder->dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct drm_crtc *crtc = encoder->crtc;
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
	int port = intel_hdmi->ddi_port;
	int pipe = intel_crtc->pipe;
	int p, n2, r2, valid=0;
	u32 temp, i;

	/* On Haswell, we need to enable the clocks and prepare DDI function to
	 * work in HDMI mode for this pipe.
	 */
	DRM_DEBUG_KMS("Preparing HDMI DDI mode for Haswell on port %c, pipe %c\n", port_name(port), pipe_name(pipe));

	for (i=0; i < DRM_ARRAY_SIZE(wrpll_tmds_clock_table); i++) {
		if (crtc->mode.clock == wrpll_tmds_clock_table[i].clock) {
			p = wrpll_tmds_clock_table[i].p;
			n2 = wrpll_tmds_clock_table[i].n2;
			r2 = wrpll_tmds_clock_table[i].r2;

			DRM_DEBUG_KMS("WR PLL clock: found settings for %dKHz refresh rate: p=%d, n2=%d, r2=%d\n",
					crtc->mode.clock,
					p, n2, r2);

			valid = 1;
			break;
		}
	}

	if (!valid) {
		DRM_ERROR("Unable to find WR PLL clock settings for %dKHz refresh rate\n",
				crtc->mode.clock);
		return;
	}

	/* Enable LCPLL if disabled */
	temp = I915_READ(LCPLL_CTL);
	if (temp & LCPLL_PLL_DISABLE)
		I915_WRITE(LCPLL_CTL,
				temp & ~LCPLL_PLL_DISABLE);

	/* Configure WR PLL 1, program the correct divider values for
	 * the desired frequency and wait for warmup */
	I915_WRITE(WRPLL_CTL1,
			WRPLL_PLL_ENABLE |
			WRPLL_PLL_SELECT_LCPLL_2700 |
			WRPLL_DIVIDER_REFERENCE(r2) |
			WRPLL_DIVIDER_FEEDBACK(n2) |
			WRPLL_DIVIDER_POST(p));

	DELAY(20);

	/* Use WRPLL1 clock to drive the output to the port, and tell the pipe to use
	 * this port for connection.
	 */
	I915_WRITE(PORT_CLK_SEL(port),
			PORT_CLK_SEL_WRPLL1);
	I915_WRITE(PIPE_CLK_SEL(pipe),
			PIPE_CLK_SEL_PORT(port));

	DELAY(20);

	if (intel_hdmi->has_audio) {
		/* Proper support for digital audio needs a new logic and a new set
		 * of registers, so we leave it for future patch bombing.
		 */
		DRM_DEBUG_DRIVER("HDMI audio on pipe %c not yet supported on DDI\n",
				 pipe_name(intel_crtc->pipe));
	}

	/* Enable PIPE_DDI_FUNC_CTL for the pipe to work in HDMI mode */
	temp = I915_READ(DDI_FUNC_CTL(pipe));
	temp &= ~PIPE_DDI_PORT_MASK;
	temp &= ~PIPE_DDI_BPC_12;
	temp |= PIPE_DDI_SELECT_PORT(port) |
			PIPE_DDI_MODE_SELECT_HDMI |
			((intel_crtc->bpp > 24) ?
				PIPE_DDI_BPC_12 :
				PIPE_DDI_BPC_8) |
			PIPE_DDI_FUNC_ENABLE;

	I915_WRITE(DDI_FUNC_CTL(pipe), temp);

	intel_hdmi_set_avi_infoframe(encoder, adjusted_mode);
	intel_hdmi_set_spd_infoframe(encoder);
}