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

Commit b3ede177 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge branch 'drm-next-4.1' of git://people.freedesktop.org/~agd5f/linux into drm-next

- DP MST support (disabled by default)
- non-ATOM aux support (DCE5+)
- output csc support for clamped RGB
- Lots of new queries for profiling, Gallium HUD, etc.
- Misc fixes

* 'drm-next-4.1' of git://people.freedesktop.org/~agd5f/linux: (40 commits)
  drm/radeon: add DisplayPort MST support (v2)
  drm/radeon: improve encoder picking functions (v2)
  drm/radeon: export max link rate calculation
  drm/radeon: add new atombios encoder/transmitter interfaces
  drm/radeon: add some MST registers
  radeon/fb: add wrapper functions around fb connector add/remove
  radeon/cik: add support for short HPD irqs
  radeon/si: add support for short HPD irqs
  radeon/evergreen: add support for short HPD irqs
  radeon: introduce a dp_work handler
  drm/dp_mst: add a function to retrieve vcpi slots
  drm/radeon: program auxch directly (v2)
  drm/radeon: fix doublescan modes (v2)
  drm/radeon: typo in parameter description
  drm/radeon: add support for read reg query from radeon info ioctl
  drm/radeon: add get_allowed_info_register for CIK
  drm/radeon: add get_allowed_info_register for SI
  drm/radeon: add get_allowed_info_register for cayman/TN
  drm/radeon: add get_allowed_info_register for EG/BTC
  drm/radeon: add get_allowed_info_register for r6xx/r7xx
  ...
parents 6b94aea0 9843ead0
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -2319,6 +2319,19 @@ bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp
}
EXPORT_SYMBOL(drm_dp_mst_allocate_vcpi);

int drm_dp_mst_get_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
{
	int slots = 0;
	port = drm_dp_get_validated_port_ref(mgr, port);
	if (!port)
		return slots;

	slots = port->vcpi.num_slots;
	drm_dp_put_port(port);
	return slots;
}
EXPORT_SYMBOL(drm_dp_mst_get_vcpi_slots);

/**
 * drm_dp_mst_reset_vcpi_slots() - Reset number of slots to 0 for VCPI
 * @mgr: manager for this port
+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_sync.o radeon_audio.o radeon_dp_auxch.o radeon_dp_mst.o

radeon-$(CONFIG_MMU_NOTIFIER) += radeon_mn.o

+22 −3
Original line number Diff line number Diff line
@@ -330,8 +330,10 @@ atombios_set_crtc_dtd_timing(struct drm_crtc *crtc,
		misc |= ATOM_COMPOSITESYNC;
	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
		misc |= ATOM_INTERLACE;
	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
		misc |= ATOM_DOUBLE_CLOCK_MODE;
	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
		misc |= ATOM_H_REPLICATIONBY2 | ATOM_V_REPLICATIONBY2;

	args.susModeMiscInfo.usAccess = cpu_to_le16(misc);
	args.ucCRTC = radeon_crtc->crtc_id;
@@ -374,8 +376,10 @@ static void atombios_crtc_set_timing(struct drm_crtc *crtc,
		misc |= ATOM_COMPOSITESYNC;
	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
		misc |= ATOM_INTERLACE;
	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
		misc |= ATOM_DOUBLE_CLOCK_MODE;
	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
		misc |= ATOM_H_REPLICATIONBY2 | ATOM_V_REPLICATIONBY2;

	args.susModeMiscInfo.usAccess = cpu_to_le16(misc);
	args.ucCRTC = radeon_crtc->crtc_id;
@@ -606,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) {
@@ -952,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 =
@@ -2069,6 +2082,12 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc,
		radeon_crtc->connector = NULL;
		return false;
	}
	if (radeon_crtc->encoder) {
		struct radeon_encoder *radeon_encoder =
			to_radeon_encoder(radeon_crtc->encoder);

		radeon_crtc->output_csc = radeon_encoder->output_csc;
	}
	if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
		return false;
	if (!atombios_crtc_prepare_pll(crtc, adjusted_mode))
+13 −4
Original line number Diff line number Diff line
@@ -158,7 +158,7 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,
#define HEADER_SIZE (BARE_ADDRESS_SIZE + 1)

static ssize_t
radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
radeon_dp_aux_transfer_atom(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
{
	struct radeon_i2c_chan *chan =
		container_of(aux, struct radeon_i2c_chan, aux);
@@ -226,11 +226,20 @@ radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)

void radeon_dp_aux_init(struct radeon_connector *radeon_connector)
{
	struct drm_device *dev = radeon_connector->base.dev;
	struct radeon_device *rdev = dev->dev_private;
	int ret;

	radeon_connector->ddc_bus->rec.hpd = radeon_connector->hpd.hpd;
	radeon_connector->ddc_bus->aux.dev = radeon_connector->base.kdev;
	radeon_connector->ddc_bus->aux.transfer = radeon_dp_aux_transfer;
	if (ASIC_IS_DCE5(rdev)) {
		if (radeon_auxch)
			radeon_connector->ddc_bus->aux.transfer = radeon_dp_aux_transfer_native;
		else
			radeon_connector->ddc_bus->aux.transfer = radeon_dp_aux_transfer_atom;
	} else {
		radeon_connector->ddc_bus->aux.transfer = radeon_dp_aux_transfer_atom;
	}

	ret = drm_dp_aux_register(&radeon_connector->ddc_bus->aux);
	if (!ret)
@@ -301,7 +310,7 @@ static int dp_get_max_dp_pix_clock(int link_rate,

/***** radeon specific DP functions *****/

static int radeon_dp_get_max_link_rate(struct drm_connector *connector,
int radeon_dp_get_max_link_rate(struct drm_connector *connector,
				u8 dpcd[DP_DPCD_SIZE])
{
	int max_link_rate;
+143 −28
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;
@@ -823,7 +831,7 @@ union dig_encoder_control {
};

void
atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode)
atombios_dig_encoder_setup2(struct drm_encoder *encoder, int action, int panel_mode, int enc_override)
{
	struct drm_device *dev = encoder->dev;
	struct radeon_device *rdev = dev->dev_private;
@@ -920,6 +928,9 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mo

			if (ENCODER_MODE_IS_DP(args.v3.ucEncoderMode) && (dp_clock == 270000))
				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
			if (enc_override != -1)
				args.v3.acConfig.ucDigSel = enc_override;
			else
				args.v3.acConfig.ucDigSel = dig->dig_encoder;
			args.v3.ucBitPerColor = radeon_atom_get_bpc(encoder);
			break;
@@ -948,6 +959,10 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mo
				else
					args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_1_62GHZ;
			}

			if (enc_override != -1)
				args.v4.acConfig.ucDigSel = enc_override;
			else
				args.v4.acConfig.ucDigSel = dig->dig_encoder;
			args.v4.ucBitPerColor = radeon_atom_get_bpc(encoder);
			if (hpd_id == RADEON_HPD_NONE)
@@ -969,6 +984,12 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mo

}

void
atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode)
{
	atombios_dig_encoder_setup2(encoder, action, panel_mode, -1);
}

union dig_transmitter_control {
	DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1;
	DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2;
@@ -978,7 +999,7 @@ union dig_transmitter_control {
};

void
atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set)
atombios_dig_transmitter_setup2(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set, int fe)
{
	struct drm_device *dev = encoder->dev;
	struct radeon_device *rdev = dev->dev_private;
@@ -1328,7 +1349,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
				args.v5.asConfig.ucHPDSel = 0;
			else
				args.v5.asConfig.ucHPDSel = hpd_id + 1;
			args.v5.ucDigEncoderSel = 1 << dig_encoder;
			args.v5.ucDigEncoderSel = (fe != -1) ? (1 << fe) : (1 << dig_encoder);
			args.v5.ucDPLaneSet = lane_set;
			break;
		default:
@@ -1344,6 +1365,12 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
}

void
atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set)
{
	atombios_dig_transmitter_setup2(encoder, action, lane_num, lane_set, -1);
}

bool
atombios_set_edp_panel_power(struct drm_connector *connector, int action)
{
@@ -1687,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);
@@ -1955,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)
@@ -2003,7 +2082,14 @@ atombios_apply_encoder_quirks(struct drm_encoder *encoder,
	}
}

static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder)
void radeon_atom_release_dig_encoder(struct radeon_device *rdev, int enc_idx)
{
	if (enc_idx < 0)
		return;
	rdev->mode_info.active_encoders &= ~(1 << enc_idx);
}

int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder, int fe_idx)
{
	struct drm_device *dev = encoder->dev;
	struct radeon_device *rdev = dev->dev_private;
@@ -2012,71 +2098,79 @@ static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder)
	struct drm_encoder *test_encoder;
	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
	uint32_t dig_enc_in_use = 0;
	int enc_idx = -1;

	if (fe_idx >= 0) {
		enc_idx = fe_idx;
		goto assigned;
	}
	if (ASIC_IS_DCE6(rdev)) {
		/* DCE6 */
		switch (radeon_encoder->encoder_id) {
		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
			if (dig->linkb)
				return 1;
				enc_idx = 1;
			else
				return 0;
				enc_idx = 0;
			break;
		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
			if (dig->linkb)
				return 3;
				enc_idx = 3;
			else
				return 2;
				enc_idx = 2;
			break;
		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
			if (dig->linkb)
				return 5;
				enc_idx = 5;
			else
				return 4;
				enc_idx = 4;
			break;
		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
			return 6;
			enc_idx = 6;
			break;
		}
		goto assigned;
	} else if (ASIC_IS_DCE4(rdev)) {
		/* DCE4/5 */
		if (ASIC_IS_DCE41(rdev) && !ASIC_IS_DCE61(rdev)) {
			/* ontario follows DCE4 */
			if (rdev->family == CHIP_PALM) {
				if (dig->linkb)
					return 1;
					enc_idx = 1;
				else
					return 0;
					enc_idx = 0;
			} else
				/* llano follows DCE3.2 */
				return radeon_crtc->crtc_id;
				enc_idx = radeon_crtc->crtc_id;
		} else {
			switch (radeon_encoder->encoder_id) {
			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
				if (dig->linkb)
					return 1;
					enc_idx = 1;
				else
					return 0;
					enc_idx = 0;
				break;
			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
				if (dig->linkb)
					return 3;
					enc_idx = 3;
				else
					return 2;
					enc_idx = 2;
				break;
			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
				if (dig->linkb)
					return 5;
					enc_idx = 5;
				else
					return 4;
					enc_idx = 4;
				break;
			}
		}
		goto assigned;
	}

	/* on DCE32 and encoder can driver any block so just crtc id */
	if (ASIC_IS_DCE32(rdev)) {
		return radeon_crtc->crtc_id;
		enc_idx = radeon_crtc->crtc_id;
		goto assigned;
	}

	/* on DCE3 - LVTMA can only be driven by DIGB */
@@ -2104,6 +2198,17 @@ static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder)
	if (!(dig_enc_in_use & 1))
		return 0;
	return 1;

assigned:
	if (enc_idx == -1) {
		DRM_ERROR("Got encoder index incorrect - returning 0\n");
		return 0;
	}
	if (rdev->mode_info.active_encoders & (1 << enc_idx)) {
		DRM_ERROR("chosen encoder in use %d\n", enc_idx);
	}
	rdev->mode_info.active_encoders |= (1 << enc_idx);
	return enc_idx;
}

/* This only needs to be called once at startup */
@@ -2362,7 +2467,9 @@ static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
	     ENCODER_OBJECT_ID_NONE)) {
		struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
		if (dig) {
			dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder);
			if (dig->dig_encoder >= 0)
				radeon_atom_release_dig_encoder(rdev, dig->dig_encoder);
			dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder, -1);
			if (radeon_encoder->active_device & ATOM_DEVICE_DFP_SUPPORT) {
				if (rdev->family >= CHIP_R600)
					dig->afmt = rdev->mode_info.afmt[dig->dig_encoder];
@@ -2464,9 +2571,17 @@ static void radeon_atom_encoder_disable(struct drm_encoder *encoder)

disable_done:
	if (radeon_encoder_is_digital(encoder)) {
		if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) {
			if (rdev->asic->display.hdmi_enable)
				radeon_hdmi_enable(rdev, encoder, false);
		}
		if (atombios_get_encoder_mode(encoder) != ATOM_ENCODER_MODE_DP_MST) {
			dig = radeon_encoder->enc_priv;
			radeon_atom_release_dig_encoder(rdev, dig->dig_encoder);
			dig->dig_encoder = -1;
			radeon_encoder->active_device = 0;
		}
	} else
		radeon_encoder->active_device = 0;
}

Loading