Ejemplo n.º 1
0
/*
 * enable the HDMI engine
 */
void r600_hdmi_enable(struct drm_encoder *encoder)
{
	struct drm_device *dev = encoder->dev;
	struct radeon_device *rdev = dev->dev_private;
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
	uint32_t offset;
	u32 hdmi;

	if (ASIC_IS_DCE6(rdev))
		return;

	/* Silent, r600_hdmi_enable will raise WARN for us */
	if (dig->afmt->enabled)
		return;
	offset = dig->afmt->offset;

	/* Older chipsets require setting HDMI and routing manually */
	if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) {
		hdmi = HDMI0_ERROR_ACK | HDMI0_ENABLE;
		switch (radeon_encoder->encoder_id) {
		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
			WREG32_P(AVIVO_TMDSA_CNTL, AVIVO_TMDSA_CNTL_HDMI_EN,
				 ~AVIVO_TMDSA_CNTL_HDMI_EN);
			hdmi |= HDMI0_STREAM(HDMI0_STREAM_TMDSA);
			break;
		case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
			WREG32_P(AVIVO_LVTMA_CNTL, AVIVO_LVTMA_CNTL_HDMI_EN,
				 ~AVIVO_LVTMA_CNTL_HDMI_EN);
			hdmi |= HDMI0_STREAM(HDMI0_STREAM_LVTMA);
			break;
		case ENCODER_OBJECT_ID_INTERNAL_DDI:
			WREG32_P(DDIA_CNTL, DDIA_HDMI_EN, ~DDIA_HDMI_EN);
			hdmi |= HDMI0_STREAM(HDMI0_STREAM_DDIA);
			break;
		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
			hdmi |= HDMI0_STREAM(HDMI0_STREAM_DVOA);
			break;
		default:
			dev_err(rdev->dev, "Invalid encoder for HDMI: 0x%X\n",
				radeon_encoder->encoder_id);
			break;
		}
		WREG32(HDMI0_CONTROL + offset, hdmi);
	}

	if (rdev->irq.installed) {
		/* if irq is available use it */
		radeon_irq_kms_enable_afmt(rdev, dig->afmt->id);
	}

	dig->afmt->enabled = true;

	DRM_DEBUG("Enabling HDMI interface @ 0x%04X for encoder 0x%x\n",
		  offset, radeon_encoder->encoder_id);
}
Ejemplo n.º 2
0
/*
 * disable the HDMI engine
 */
void r600_hdmi_disable(struct drm_encoder *encoder)
{
	struct drm_device *dev = encoder->dev;
	struct radeon_device *rdev = dev->dev_private;
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
	uint32_t offset;

	if (ASIC_IS_DCE6(rdev))
		return;

	/* Called for ATOM_ENCODER_MODE_HDMI only */
	if (!dig || !dig->afmt) {
		return;
	}
	if (!dig->afmt->enabled)
		return;
	offset = dig->afmt->offset;

	DRM_DEBUG("Disabling HDMI interface @ 0x%04X for encoder 0x%x\n",
		  offset, radeon_encoder->encoder_id);

	/* disable irq */
	radeon_irq_kms_disable_afmt(rdev, dig->afmt->id);

	/* Older chipsets not handled by AtomBIOS */
	if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) {
		switch (radeon_encoder->encoder_id) {
		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
			WREG32_P(AVIVO_TMDSA_CNTL, 0,
				 ~AVIVO_TMDSA_CNTL_HDMI_EN);
			break;
		case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
			WREG32_P(AVIVO_LVTMA_CNTL, 0,
				 ~AVIVO_LVTMA_CNTL_HDMI_EN);
			break;
		case ENCODER_OBJECT_ID_INTERNAL_DDI:
			WREG32_P(DDIA_CNTL, 0, ~DDIA_HDMI_EN);
			break;
		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
			break;
		default:
			dev_err(rdev->dev, "Invalid encoder for HDMI: 0x%X\n",
				radeon_encoder->encoder_id);
			break;
		}
		WREG32(HDMI0_CONTROL + offset, HDMI0_ERROR_ACK);
	}

	dig->afmt->enabled = false;
}
Ejemplo n.º 3
0
void evergreen_dp_enable(struct drm_encoder *encoder, bool enable)
{
	struct drm_device *dev = encoder->dev;
	struct radeon_device *rdev = dev->dev_private;
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);

	if (!dig || !dig->afmt)
		return;

	if (enable && drm_detect_monitor_audio(radeon_connector_edid(connector))) {
		struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
		struct radeon_connector_atom_dig *dig_connector;
		uint32_t val;

		WREG32_OR(AFMT_AUDIO_PACKET_CONTROL + dig->afmt->offset,
			  AFMT_AUDIO_SAMPLE_SEND);

		WREG32(EVERGREEN_DP_SEC_TIMESTAMP + dig->afmt->offset,
		       EVERGREEN_DP_SEC_TIMESTAMP_MODE(1));

		if (!ASIC_IS_DCE6(rdev) && radeon_connector->con_priv) {
			dig_connector = radeon_connector->con_priv;
			val = RREG32(EVERGREEN_DP_SEC_AUD_N + dig->afmt->offset);
			val &= ~EVERGREEN_DP_SEC_N_BASE_MULTIPLE(0xf);

			if (dig_connector->dp_clock == 162000)
				val |= EVERGREEN_DP_SEC_N_BASE_MULTIPLE(3);
			else
				val |= EVERGREEN_DP_SEC_N_BASE_MULTIPLE(5);

			WREG32(EVERGREEN_DP_SEC_AUD_N + dig->afmt->offset, val);
		}

		WREG32(EVERGREEN_DP_SEC_CNTL + dig->afmt->offset,
			EVERGREEN_DP_SEC_ASP_ENABLE |		/* Audio packet transmission */
			EVERGREEN_DP_SEC_ATP_ENABLE |		/* Audio timestamp packet transmission */
			EVERGREEN_DP_SEC_AIP_ENABLE |		/* Audio infoframe packet transmission */
			EVERGREEN_DP_SEC_STREAM_ENABLE);	/* Master enable for secondary stream engine */
	} else {
		WREG32(EVERGREEN_DP_SEC_CNTL + dig->afmt->offset, 0);
		WREG32_AND(AFMT_AUDIO_PACKET_CONTROL + dig->afmt->offset,
			   ~AFMT_AUDIO_SAMPLE_SEND);
	}

	dig->afmt->enabled = enable;
}