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

Commit 9843ead0 authored by Dave Airlie's avatar Dave Airlie Committed by Alex Deucher
Browse files

drm/radeon: add DisplayPort MST support (v2)



This adds initial DP 1.2 MST support to radeon, on CAYMAN
and up in theory.

This is off by default.

v2: agd5f:
- add UNIPHY3 offsets
- move atom cmd table code into atombios_encoders.c
- whitespace cleanup
- replace some magic numbers with proper defines

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 8f0fc088
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -81,7 +81,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
	rv770_smc.o cypress_dpm.o btc_dpm.o sumo_dpm.o sumo_smc.o trinity_dpm.o \
	trinity_smc.o ni_dpm.o si_smc.o si_dpm.o kv_smc.o kv_dpm.o ci_smc.o \
	ci_dpm.o dce6_afmt.o radeon_vm.o radeon_ucode.o radeon_ib.o \
	radeon_sync.o radeon_audio.o radeon_dp_auxch.o
	radeon_sync.o radeon_audio.o radeon_dp_auxch.o radeon_dp_mst.o

radeon-$(CONFIG_MMU_NOTIFIER) += radeon_mn.o

+10 −1
Original line number Diff line number Diff line
@@ -610,6 +610,13 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
		}
	}

	if (radeon_encoder->is_mst_encoder) {
		struct radeon_encoder_mst *mst_enc = radeon_encoder->enc_priv;
		struct radeon_connector_atom_dig *dig_connector = mst_enc->connector->con_priv;

		dp_clock = dig_connector->dp_clock;
	}

	/* use recommended ref_div for ss */
	if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
		if (radeon_crtc->ss_enabled) {
@@ -956,7 +963,9 @@ static bool atombios_crtc_prepare_pll(struct drm_crtc *crtc, struct drm_display_
	radeon_crtc->bpc = 8;
	radeon_crtc->ss_enabled = false;

	if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) ||
	if (radeon_encoder->is_mst_encoder) {
		radeon_dp_mst_prepare_pll(crtc, mode);
	} else if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) ||
	    (radeon_encoder_get_dp_bridge_encoder_id(radeon_crtc->encoder) != ENCODER_OBJECT_ID_NONE)) {
		struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
		struct drm_connector *connector =
+60 −0
Original line number Diff line number Diff line
@@ -671,7 +671,15 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
	struct drm_connector *connector;
	struct radeon_connector *radeon_connector;
	struct radeon_connector_atom_dig *dig_connector;
	struct radeon_encoder_atom_dig *dig_enc;

	if (radeon_encoder_is_digital(encoder)) {
		dig_enc = radeon_encoder->enc_priv;
		if (dig_enc->active_mst_links)
			return ATOM_ENCODER_MODE_DP_MST;
	}
	if (radeon_encoder->is_mst_encoder || radeon_encoder->offset)
		return ATOM_ENCODER_MODE_DP_MST;
	/* dp bridges are always DP */
	if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)
		return ATOM_ENCODER_MODE_DP;
@@ -1706,6 +1714,11 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
	case DRM_MODE_DPMS_STANDBY:
	case DRM_MODE_DPMS_SUSPEND:
	case DRM_MODE_DPMS_OFF:

		/* don't power off encoders with active MST links */
		if (dig->active_mst_links)
			return;

		if (ASIC_IS_DCE4(rdev)) {
			if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector)
				atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
@@ -1974,6 +1987,53 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder)
	radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
}

void
atombios_set_mst_encoder_crtc_source(struct drm_encoder *encoder, int fe)
{
	struct drm_device *dev = encoder->dev;
	struct radeon_device *rdev = dev->dev_private;
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
	int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
	uint8_t frev, crev;
	union crtc_source_param args;

	memset(&args, 0, sizeof(args));

	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
		return;

	if (frev != 1 && crev != 2)
		DRM_ERROR("Unknown table for MST %d, %d\n", frev, crev);

	args.v2.ucCRTC = radeon_crtc->crtc_id;
	args.v2.ucEncodeMode = ATOM_ENCODER_MODE_DP_MST;

	switch (fe) {
	case 0:
		args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
		break;
	case 1:
		args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
		break;
	case 2:
		args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID;
		break;
	case 3:
		args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID;
		break;
	case 4:
		args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID;
		break;
	case 5:
		args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID;
		break;
	case 6:
		args.v2.ucEncoderID = ASIC_INT_DIG7_ENCODER_ID;
		break;
	}
	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
}

static void
atombios_apply_encoder_quirks(struct drm_encoder *encoder,
			      struct drm_display_mode *mode)
+7 −0
Original line number Diff line number Diff line
@@ -93,6 +93,8 @@
#       define NI_DP_MSE_ZERO_ENCODER                  (((x) & 0x1) << 8)

#define NI_DP_MSE_RATE_CNTL                            0x7384
#       define NI_DP_MSE_RATE_Y(x)                   (((x) & 0x3ffffff) << 0)
#       define NI_DP_MSE_RATE_X(x)                   (((x) & 0x3f) << 26)

#define NI_DP_MSE_RATE_UPDATE                          0x738c

@@ -111,6 +113,11 @@
#define NI_DIG_BE_CNTL                                 0x7140
#       define NI_DIG_FE_SOURCE_SELECT(x)              (((x) & 0x7f) << 8)
#       define NI_DIG_FE_DIG_MODE(x)                   (((x) & 0x7) << 16)
#       define NI_DIG_MODE_DP_SST                      0
#       define NI_DIG_MODE_LVDS                        1
#       define NI_DIG_MODE_TMDS_DVI                    2
#       define NI_DIG_MODE_TMDS_HDMI                   3
#       define NI_DIG_MODE_DP_MST                      5
#       define NI_DIG_HPD_SELECT(x)                    (((x) & 0x7) << 28)

#define NI_DIG_FE_CNTL                                 0x7000
+1 −0
Original line number Diff line number Diff line
@@ -112,6 +112,7 @@ extern int radeon_use_pflipirq;
extern int radeon_bapm;
extern int radeon_backlight;
extern int radeon_auxch;
extern int radeon_mst;

/*
 * Copy from radeon_drv.h so we don't have to include both and have conflicting
Loading