Ejemplo n.º 1
0
static void ibx_set_infoframes(struct drm_encoder *encoder,
			       struct drm_display_mode *adjusted_mode)
{
	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
	struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
	struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi;
	u32 reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
	u32 val = I915_READ(reg);
	u32 port;

	assert_hdmi_port_disabled(intel_hdmi);

	/* See the big comment in g4x_set_infoframes() */
	val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC;

	if (!intel_hdmi->has_hdmi_sink) {
		if (!(val & VIDEO_DIP_ENABLE))
			return;
		val &= ~VIDEO_DIP_ENABLE;
		I915_WRITE(reg, val);
		POSTING_READ(reg);
		return;
	}

	switch (intel_dig_port->port) {
	case PORT_B:
		port = VIDEO_DIP_PORT_B;
		break;
	case PORT_C:
		port = VIDEO_DIP_PORT_C;
		break;
	case PORT_D:
		port = VIDEO_DIP_PORT_D;
		break;
	default:
		BUG();
		return;
	}

	if (port != (val & VIDEO_DIP_PORT_MASK)) {
		if (val & VIDEO_DIP_ENABLE) {
			val &= ~VIDEO_DIP_ENABLE;
			I915_WRITE(reg, val);
			POSTING_READ(reg);
		}
		val &= ~VIDEO_DIP_PORT_MASK;
		val |= port;
	}

	val |= VIDEO_DIP_ENABLE;
	val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT |
		 VIDEO_DIP_ENABLE_GCP);

	I915_WRITE(reg, val);
	POSTING_READ(reg);

	intel_hdmi_set_avi_infoframe(encoder, adjusted_mode);
	intel_hdmi_set_spd_infoframe(encoder);
}
Ejemplo n.º 2
0
static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
{
	struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
	struct drm_device *dev = encoder->base.dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct intel_crtc *intel_crtc =
		to_intel_crtc(encoder->base.crtc);
	enum dpio_channel port = vlv_dport_to_channel(dport);
	int pipe = intel_crtc->pipe;

	if (!IS_VALLEYVIEW(dev))
		return;

	/* Program Tx lane resets to default */
	mutex_lock(&dev_priv->dpio_lock);
	vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port),
			 DPIO_PCS_TX_LANE2_RESET |
			 DPIO_PCS_TX_LANE1_RESET);
	vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW1(port),
			 DPIO_PCS_CLK_CRI_RXEB_EIOS_EN |
			 DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN |
			 (1<<DPIO_PCS_CLK_DATAWIDTH_SHIFT) |
			 DPIO_PCS_CLK_SOFT_RESET);

	/* Fix up inter-pair skew failure */
	vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW12(port), 0x00750f00);
	vlv_dpio_write(dev_priv, pipe, VLV_TX_DW11(port), 0x00001500);
	vlv_dpio_write(dev_priv, pipe, VLV_TX_DW14(port), 0x40400000);

	vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW9(port), 0x00002000);
	vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), DPIO_TX_OCALINIT_EN);
	mutex_unlock(&dev_priv->dpio_lock);
}
Ejemplo n.º 3
0
static void intel_hdmi_pre_pll_enable(struct intel_encoder *encoder)
{
	struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
	struct drm_device *dev = encoder->base.dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	int port = vlv_dport_to_channel(dport);

	if (!IS_VALLEYVIEW(dev))
		return;

	/* Program Tx lane resets to default */
	vlv_dpio_write(dev_priv, DPIO_PCS_TX(port),
			 DPIO_PCS_TX_LANE2_RESET |
			 DPIO_PCS_TX_LANE1_RESET);
	vlv_dpio_write(dev_priv, DPIO_PCS_CLK(port),
			 DPIO_PCS_CLK_CRI_RXEB_EIOS_EN |
			 DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN |
			 (1<<DPIO_PCS_CLK_DATAWIDTH_SHIFT) |
			 DPIO_PCS_CLK_SOFT_RESET);

	/* Fix up inter-pair skew failure */
	vlv_dpio_write(dev_priv, DPIO_PCS_STAGGER1(port), 0x00750f00);
	vlv_dpio_write(dev_priv, DPIO_TX_CTL(port), 0x00001500);
	vlv_dpio_write(dev_priv, DPIO_TX_LANE(port), 0x40400000);

	vlv_dpio_write(dev_priv, DPIO_PCS_CTL_OVER1(port),
			 0x00002000);
	vlv_dpio_write(dev_priv, DPIO_TX_OCALINIT(port),
			 DPIO_TX_OCALINIT_EN);
}
Ejemplo n.º 4
0
static int i9xx_pipe_crc_auto_source(struct drm_i915_private *dev_priv,
				     enum pipe pipe,
				     enum intel_pipe_crc_source *source)
{
	struct drm_device *dev = &dev_priv->drm;
	struct intel_encoder *encoder;
	struct intel_crtc *crtc;
	struct intel_digital_port *dig_port;
	int ret = 0;

	*source = INTEL_PIPE_CRC_SOURCE_PIPE;

	drm_modeset_lock_all(dev);
	for_each_intel_encoder(dev, encoder) {
		if (!encoder->base.crtc)
			continue;

		crtc = to_intel_crtc(encoder->base.crtc);

		if (crtc->pipe != pipe)
			continue;

		switch (encoder->type) {
		case INTEL_OUTPUT_TVOUT:
			*source = INTEL_PIPE_CRC_SOURCE_TV;
			break;
		case INTEL_OUTPUT_DP:
		case INTEL_OUTPUT_EDP:
			dig_port = enc_to_dig_port(&encoder->base);
			switch (dig_port->port) {
			case PORT_B:
				*source = INTEL_PIPE_CRC_SOURCE_DP_B;
				break;
			case PORT_C:
				*source = INTEL_PIPE_CRC_SOURCE_DP_C;
				break;
			case PORT_D:
				*source = INTEL_PIPE_CRC_SOURCE_DP_D;
				break;
			default:
				WARN(1, "nonexisting DP port %c\n",
				     port_name(dig_port->port));
				break;
			}
			break;
		default:
			break;
		}
	}
	drm_modeset_unlock_all(dev);

	return ret;
}
Ejemplo n.º 5
0
void lspcon_set_infoframes(struct intel_encoder *encoder,
			   bool enable,
			   const struct intel_crtc_state *crtc_state,
			   const struct drm_connector_state *conn_state)
{
	ssize_t ret;
	union hdmi_infoframe frame;
	u8 buf[VIDEO_DIP_DATA_SIZE];
	struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base);
	struct intel_lspcon *lspcon = &dig_port->lspcon;
	const struct drm_display_mode *adjusted_mode =
		&crtc_state->base.adjusted_mode;

	if (!lspcon->active) {
		DRM_ERROR("Writing infoframes while LSPCON disabled ?\n");
		return;
	}

	/* FIXME precompute infoframes */

	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
						       conn_state->connector,
						       adjusted_mode);
	if (ret < 0) {
		DRM_ERROR("couldn't fill AVI infoframe\n");
		return;
	}

	if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444) {
		if (crtc_state->lspcon_downsampling)
			frame.avi.colorspace = HDMI_COLORSPACE_YUV420;
		else
			frame.avi.colorspace = HDMI_COLORSPACE_YUV444;
	} else {
		frame.avi.colorspace = HDMI_COLORSPACE_RGB;
	}

	drm_hdmi_avi_infoframe_quant_range(&frame.avi,
					   conn_state->connector,
					   adjusted_mode,
					   crtc_state->limited_color_range ?
					   HDMI_QUANTIZATION_RANGE_LIMITED :
					   HDMI_QUANTIZATION_RANGE_FULL);

	ret = hdmi_infoframe_pack(&frame, buf, sizeof(buf));
	if (ret < 0) {
		DRM_ERROR("Failed to pack AVI IF\n");
		return;
	}

	dig_port->write_infoframe(encoder, crtc_state, HDMI_INFOFRAME_TYPE_AVI,
				  buf, ret);
}
Ejemplo n.º 6
0
static void intel_hdmi_post_disable(struct intel_encoder *encoder)
{
	struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
	int port = vlv_dport_to_channel(dport);

	/* Reset lanes to avoid HDMI flicker (VLV w/a) */
	mutex_lock(&dev_priv->dpio_lock);
	vlv_dpio_write(dev_priv, DPIO_PCS_TX(port), 0x00000000);
	vlv_dpio_write(dev_priv, DPIO_PCS_CLK(port), 0x00e00060);
	mutex_unlock(&dev_priv->dpio_lock);
}
Ejemplo n.º 7
0
static void vlv_hdmi_pre_enable(struct intel_encoder *encoder)
{
	struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
	struct drm_device *dev = encoder->base.dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct intel_crtc *intel_crtc =
		to_intel_crtc(encoder->base.crtc);
	int port = vlv_dport_to_channel(dport);
	int pipe = intel_crtc->pipe;
	u32 val;

	if (!IS_VALLEYVIEW(dev))
		return;

	/* Enable clock channels for this port */
	mutex_lock(&dev_priv->dpio_lock);
	val = vlv_dpio_read(dev_priv, pipe, DPIO_DATA_LANE_A(port));
	val = 0;
	if (pipe)
		val |= (1<<21);
	else
		val &= ~(1<<21);
	val |= 0x001000c4;
	vlv_dpio_write(dev_priv, pipe, DPIO_DATA_CHANNEL(port), val);

	/* HDMI 1.0V-2dB */
	vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port), 0);
	vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL4(port),
			 0x2b245f5f);
	vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL2(port),
			 0x5578b83a);
	vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL3(port),
			 0x0c782040);
	vlv_dpio_write(dev_priv, pipe, DPIO_TX3_SWING_CTL4(port),
			 0x2b247878);
	vlv_dpio_write(dev_priv, pipe, DPIO_PCS_STAGGER0(port), 0x00030000);
	vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CTL_OVER1(port),
			 0x00002000);
	vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port),
			 DPIO_TX_OCALINIT_EN);

	/* Program lane clock */
	vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLOCKBUF0(port),
			 0x00760018);
	vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLOCKBUF8(port),
			 0x00400888);
	mutex_unlock(&dev_priv->dpio_lock);

	intel_enable_hdmi(encoder);

	vlv_wait_port_ready(dev_priv, port);
}
Ejemplo n.º 8
0
static void intel_ddi_mode_set(struct intel_encoder *encoder)
{
	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
	int port = intel_ddi_get_encoder_port(encoder);
	int pipe = crtc->pipe;
	int type = encoder->type;
	struct drm_display_mode *adjusted_mode = &crtc->config.adjusted_mode;

	DRM_DEBUG_KMS("Preparing DDI mode on port %c, pipe %c\n",
		      port_name(port), pipe_name(pipe));

	crtc->eld_vld = false;
	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
		struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
		struct intel_digital_port *intel_dig_port =
			enc_to_dig_port(&encoder->base);

		intel_dp->DP = intel_dig_port->saved_port_bits |
			       DDI_BUF_CTL_ENABLE | DDI_BUF_EMP_400MV_0DB_HSW;
		intel_dp->DP |= DDI_PORT_WIDTH(intel_dp->lane_count);

		if (intel_dp->has_audio) {
			DRM_DEBUG_DRIVER("DP audio on pipe %c on DDI\n",
					 pipe_name(crtc->pipe));

			/* write eld */
			DRM_DEBUG_DRIVER("DP audio: write eld information\n");
			intel_write_eld(&encoder->base, adjusted_mode);
		}

		intel_dp_init_link_config(intel_dp);

	} else if (type == INTEL_OUTPUT_HDMI) {
		struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);

		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 on DDI\n",
					 pipe_name(crtc->pipe));

			/* write eld */
			DRM_DEBUG_DRIVER("HDMI audio: write eld information\n");
			intel_write_eld(&encoder->base, adjusted_mode);
		}

		intel_hdmi->set_infoframes(&encoder->base, adjusted_mode);
	}
}
Ejemplo n.º 9
0
static void vlv_hdmi_post_disable(struct intel_encoder *encoder)
{
	struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
	struct intel_crtc *intel_crtc =
		to_intel_crtc(encoder->base.crtc);
	enum dpio_channel port = vlv_dport_to_channel(dport);
	int pipe = intel_crtc->pipe;

	/* Reset lanes to avoid HDMI flicker (VLV w/a) */
	mutex_lock(&dev_priv->dpio_lock);
	vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port), 0x00000000);
	vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW1(port), 0x00e00060);
	mutex_unlock(&dev_priv->dpio_lock);
}
Ejemplo n.º 10
0
static void intel_enable_hdmi(struct intel_encoder *encoder)
{
	struct drm_device *dev = encoder->base.dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
	u32 temp;
	u32 enable_bits = SDVO_ENABLE;

	if (intel_hdmi->has_audio)
		enable_bits |= SDVO_AUDIO_ENABLE;

	temp = I915_READ(intel_hdmi->hdmi_reg);

	/* HW workaround for IBX, we need to move the port to transcoder A
	 * before disabling it, so restore the transcoder select bit here. */
	if (HAS_PCH_IBX(dev))
		enable_bits |= SDVO_PIPE_SEL(intel_crtc->pipe);

	/* HW workaround, need to toggle enable bit off and on for 12bpc, but
	 * we do this anyway which shows more stable in testing.
	 */
	if (HAS_PCH_SPLIT(dev)) {
		I915_WRITE(intel_hdmi->hdmi_reg, temp & ~SDVO_ENABLE);
		POSTING_READ(intel_hdmi->hdmi_reg);
	}

	temp |= enable_bits;

	I915_WRITE(intel_hdmi->hdmi_reg, temp);
	POSTING_READ(intel_hdmi->hdmi_reg);

	/* HW workaround, need to write this twice for issue that may result
	 * in first write getting masked.
	 */
	if (HAS_PCH_SPLIT(dev)) {
		I915_WRITE(intel_hdmi->hdmi_reg, temp);
		POSTING_READ(intel_hdmi->hdmi_reg);
	}

	if (IS_VALLEYVIEW(dev)) {
		struct intel_digital_port *dport =
			enc_to_dig_port(&encoder->base);
		int channel = vlv_dport_to_channel(dport);

		vlv_wait_port_ready(dev_priv, channel);
	}
}
Ejemplo n.º 11
0
static enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder)
{
	struct drm_encoder *encoder = &intel_encoder->base;
	int type = intel_encoder->type;

	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP ||
	    type == INTEL_OUTPUT_HDMI || type == INTEL_OUTPUT_UNKNOWN) {
		struct intel_digital_port *intel_dig_port =
			enc_to_dig_port(encoder);
		return intel_dig_port->port;

	} else if (type == INTEL_OUTPUT_ANALOG) {
		return PORT_E;

	} else {
		panic("Invalid DDI encoder type %d\n", type);
	}
}
Ejemplo n.º 12
0
static void g4x_set_infoframes(struct drm_encoder *encoder,
			       struct drm_display_mode *adjusted_mode)
{
	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
	struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
	struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi;
	u32 reg = VIDEO_DIP_CTL;
	u32 val = I915_READ(reg);
	u32 port;

	assert_hdmi_port_disabled(intel_hdmi);

	/* If the registers were not initialized yet, they might be zeroes,
	 * which means we're selecting the AVI DIP and we're setting its
	 * frequency to once. This seems to really confuse the HW and make
	 * things stop working (the register spec says the AVI always needs to
	 * be sent every VSync). So here we avoid writing to the register more
	 * than we need and also explicitly select the AVI DIP and explicitly
	 * set its frequency to every VSync. Avoiding to write it twice seems to
	 * be enough to solve the problem, but being defensive shouldn't hurt us
	 * either. */
	val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC;

	if (!intel_hdmi->has_hdmi_sink) {
		if (!(val & VIDEO_DIP_ENABLE))
			return;
		val &= ~VIDEO_DIP_ENABLE;
		I915_WRITE(reg, val);
		POSTING_READ(reg);
		return;
	}

	switch (intel_dig_port->port) {
	case PORT_B:
		port = VIDEO_DIP_PORT_B;
		break;
	case PORT_C:
		port = VIDEO_DIP_PORT_C;
		break;
	default:
		BUG();
		return;
	}

	if (port != (val & VIDEO_DIP_PORT_MASK)) {
		if (val & VIDEO_DIP_ENABLE) {
			val &= ~VIDEO_DIP_ENABLE;
			I915_WRITE(reg, val);
			POSTING_READ(reg);
		}
		val &= ~VIDEO_DIP_PORT_MASK;
		val |= port;
	}

	val |= VIDEO_DIP_ENABLE;
	val &= ~VIDEO_DIP_ENABLE_VENDOR;

	I915_WRITE(reg, val);
	POSTING_READ(reg);

	intel_hdmi_set_avi_infoframe(encoder, adjusted_mode);
	intel_hdmi_set_spd_infoframe(encoder);
	intel_hdmi_set_hdmi_infoframe(encoder, adjusted_mode);
}
Ejemplo n.º 13
0
static void intel_ddi_mode_set(struct drm_encoder *encoder,
			       struct drm_display_mode *mode,
			       struct drm_display_mode *adjusted_mode)
{
	struct drm_crtc *crtc = encoder->crtc;
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
	struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
	int port = intel_ddi_get_encoder_port(intel_encoder);
	int pipe = intel_crtc->pipe;
	int type = intel_encoder->type;

	DRM_DEBUG_KMS("Preparing DDI mode for Haswell on port %c, pipe %c\n",
		      port_name(port), pipe_name(pipe));

	intel_crtc->eld_vld = false;
	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
		struct intel_digital_port *intel_dig_port =
			enc_to_dig_port(encoder);

		intel_dp->DP = intel_dig_port->port_reversal |
			       DDI_BUF_CTL_ENABLE | DDI_BUF_EMP_400MV_0DB_HSW;
		switch (intel_dp->lane_count) {
		case 1:
			intel_dp->DP |= DDI_PORT_WIDTH_X1;
			break;
		case 2:
			intel_dp->DP |= DDI_PORT_WIDTH_X2;
			break;
		case 4:
			intel_dp->DP |= DDI_PORT_WIDTH_X4;
			break;
		default:
			intel_dp->DP |= DDI_PORT_WIDTH_X4;
			WARN(1, "Unexpected DP lane count %d\n",
			     intel_dp->lane_count);
			break;
		}

		if (intel_dp->has_audio) {
			DRM_DEBUG_DRIVER("DP audio on pipe %c on DDI\n",
					 pipe_name(intel_crtc->pipe));

			/* write eld */
			DRM_DEBUG_DRIVER("DP audio: write eld information\n");
			intel_write_eld(encoder, adjusted_mode);
		}

		intel_dp_init_link_config(intel_dp);

	} else if (type == INTEL_OUTPUT_HDMI) {
		struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);

		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 on DDI\n",
					 pipe_name(intel_crtc->pipe));

			/* write eld */
			DRM_DEBUG_DRIVER("HDMI audio: write eld information\n");
			intel_write_eld(encoder, adjusted_mode);
		}

		intel_hdmi->set_infoframes(encoder, adjusted_mode);
	}
}