Commit 27f44325 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'topic/amdgpu-dp2.0-mst-2021-10-27' of...

Merge tag 'topic/amdgpu-dp2.0-mst-2021-10-27' of git://anongit.freedesktop.org/drm/drm-misc

 into drm-next

UAPI Changes:
Nope!

Cross-subsystem Changes:
drm_dp_update_payload_part1() takes a new argument for specifying what the
VCPI slot start is

Core Changes:
Make the DP MST helpers aware of the current starting VCPI slot/VCPI total
slot count...

Driver Changes:
...and then add support for taking advantage of this for 128b/132b links on DP
2.0 for amdgpu

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
From: Lyude Paul <lyude@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/bf8e724cc0c8803d58a8d730fd6883c991376a76.camel@redhat.com
parents 367fe8dc 00f965e7
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -10669,6 +10669,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
	struct dm_crtc_state *dm_old_crtc_state;
#if defined(CONFIG_DRM_AMD_DC_DCN)
	struct dsc_mst_fairness_vars vars[MAX_PIPES];
	struct drm_dp_mst_topology_state *mst_state;
	struct drm_dp_mst_topology_mgr *mgr;
#endif

	trace_amdgpu_dm_atomic_check_begin(state);
@@ -10873,6 +10875,33 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
		lock_and_validation_needed = true;
	}

#if defined(CONFIG_DRM_AMD_DC_DCN)
	/* set the slot info for each mst_state based on the link encoding format */
	for_each_new_mst_mgr_in_state(state, mgr, mst_state, i) {
		struct amdgpu_dm_connector *aconnector;
		struct drm_connector *connector;
		struct drm_connector_list_iter iter;
		u8 link_coding_cap;

		if (!mgr->mst_state )
			continue;

		drm_connector_list_iter_begin(dev, &iter);
		drm_for_each_connector_iter(connector, &iter) {
			int id = connector->index;

			if (id == mst_state->mgr->conn_base_id) {
				aconnector = to_amdgpu_dm_connector(connector);
				link_coding_cap = dc_link_dp_mst_decide_link_encoding_format(aconnector->dc_link);
				drm_dp_mst_update_slots(mst_state, link_coding_cap);

				break;
			}
		}
		drm_connector_list_iter_end(&iter);

	}
#endif
	/**
	 * Streams and planes are reset when there are changes that affect
	 * bandwidth. Anything that affects bandwidth needs to go through
+3 −0
Original line number Diff line number Diff line
@@ -294,6 +294,9 @@ static ssize_t dp_link_settings_write(struct file *f, const char __user *buf,
	case LINK_RATE_RBR2:
	case LINK_RATE_HIGH2:
	case LINK_RATE_HIGH3:
#if defined(CONFIG_DRM_AMD_DC_DCN)
	case LINK_RATE_UHBR10:
#endif
		break;
	default:
		valid_input = false;
+6 −1
Original line number Diff line number Diff line
@@ -219,6 +219,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
	struct drm_dp_mst_topology_mgr *mst_mgr;
	struct drm_dp_mst_port *mst_port;
	bool ret;
	u8 link_coding_cap = DP_8b_10b_ENCODING;

	aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
	/* Accessing the connector state is required for vcpi_slots allocation
@@ -238,6 +239,10 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(

	mst_port = aconnector->port;

#if defined(CONFIG_DRM_AMD_DC_DCN)
	link_coding_cap = dc_link_dp_mst_decide_link_encoding_format(aconnector->dc_link);
#endif

	if (enable) {

		ret = drm_dp_mst_allocate_vcpi(mst_mgr, mst_port,
@@ -251,7 +256,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
	}

	/* It's OK for this to fail */
	drm_dp_update_payload_part1(mst_mgr);
	drm_dp_update_payload_part1(mst_mgr, (link_coding_cap == DP_CAP_ANSI_128B132B) ? 0:1);

	/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
	 * AUX message. The sequence is slot 1-63 allocated sequence for each
+14 −0
Original line number Diff line number Diff line
@@ -2354,6 +2354,11 @@ static enum surface_update_type check_update_surfaces_for_stream(
		if (stream_update->dsc_config)
			su_flags->bits.dsc_changed = 1;

#if defined(CONFIG_DRM_AMD_DC_DCN)
		if (stream_update->mst_bw_update)
			su_flags->bits.mst_bw = 1;
#endif

		if (su_flags->raw != 0)
			overall_type = UPDATE_TYPE_FULL;

@@ -2731,6 +2736,15 @@ static void commit_planes_do_stream_update(struct dc *dc,
			if (stream_update->dsc_config)
				dp_update_dsc_config(pipe_ctx);

#if defined(CONFIG_DRM_AMD_DC_DCN)
			if (stream_update->mst_bw_update) {
				if (stream_update->mst_bw_update->is_increase)
					dc_link_increase_mst_payload(pipe_ctx, stream_update->mst_bw_update->mst_stream_bw);
				else
					dc_link_reduce_mst_payload(pipe_ctx, stream_update->mst_bw_update->mst_stream_bw);
			}
#endif

			if (stream_update->pending_test_pattern) {
				dc_link_dp_set_test_pattern(stream->link,
					stream->test_pattern.type,
+292 −0
Original line number Diff line number Diff line
@@ -3232,6 +3232,9 @@ static struct fixed31_32 get_pbn_from_timing(struct pipe_ctx *pipe_ctx)
static void update_mst_stream_alloc_table(
	struct dc_link *link,
	struct stream_encoder *stream_enc,
#if defined(CONFIG_DRM_AMD_DC_DCN)
	struct hpo_dp_stream_encoder *hpo_dp_stream_enc, // TODO: Rename stream_enc to dio_stream_enc?
#endif
	const struct dp_mst_stream_allocation_table *proposed_table)
{
	struct link_mst_stream_allocation work_table[MAX_CONTROLLER_NUM] = { 0 };
@@ -3267,6 +3270,9 @@ static void update_mst_stream_alloc_table(
			work_table[i].slot_count =
				proposed_table->stream_allocations[i].slot_count;
			work_table[i].stream_enc = stream_enc;
#if defined(CONFIG_DRM_AMD_DC_DCN)
			work_table[i].hpo_dp_stream_enc = hpo_dp_stream_enc;
#endif
		}
	}

@@ -3389,6 +3395,10 @@ enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx)
	struct dc_link *link = stream->link;
	struct link_encoder *link_encoder = NULL;
	struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc;
#if defined(CONFIG_DRM_AMD_DC_DCN)
	struct hpo_dp_link_encoder *hpo_dp_link_encoder = link->hpo_dp_link_enc;
	struct hpo_dp_stream_encoder *hpo_dp_stream_encoder = pipe_ctx->stream_res.hpo_dp_stream_enc;
#endif
	struct dp_mst_stream_allocation_table proposed_table = {0};
	struct fixed31_32 avg_time_slots_per_mtp;
	struct fixed31_32 pbn;
@@ -3416,7 +3426,14 @@ enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx)
		&proposed_table,
		true)) {
		update_mst_stream_alloc_table(
#if defined(CONFIG_DRM_AMD_DC_DCN)
					link,
					pipe_ctx->stream_res.stream_enc,
					pipe_ctx->stream_res.hpo_dp_stream_enc,
					&proposed_table);
#else
					link, pipe_ctx->stream_res.stream_enc, &proposed_table);
#endif
	}
	else
		DC_LOG_WARNING("Failed to update"
@@ -3430,6 +3447,20 @@ enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx)
			link->mst_stream_alloc_table.stream_count);

	for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
#if defined(CONFIG_DRM_AMD_DC_DCN)
		DC_LOG_MST("stream_enc[%d]: %p      "
		"stream[%d].hpo_dp_stream_enc: %p      "
		"stream[%d].vcp_id: %d      "
		"stream[%d].slot_count: %d\n",
		i,
		(void *) link->mst_stream_alloc_table.stream_allocations[i].stream_enc,
		i,
		(void *) link->mst_stream_alloc_table.stream_allocations[i].hpo_dp_stream_enc,
		i,
		link->mst_stream_alloc_table.stream_allocations[i].vcp_id,
		i,
		link->mst_stream_alloc_table.stream_allocations[i].slot_count);
#else
		DC_LOG_MST("stream_enc[%d]: %p      "
		"stream[%d].vcp_id: %d      "
		"stream[%d].slot_count: %d\n",
@@ -3439,14 +3470,33 @@ enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx)
		link->mst_stream_alloc_table.stream_allocations[i].vcp_id,
		i,
		link->mst_stream_alloc_table.stream_allocations[i].slot_count);
#endif
	}

	ASSERT(proposed_table.stream_count > 0);

	/* program DP source TX for payload */
#if defined(CONFIG_DRM_AMD_DC_DCN)
	switch (dp_get_link_encoding_format(&link->cur_link_settings)) {
	case DP_8b_10b_ENCODING:
		link_encoder->funcs->update_mst_stream_allocation_table(
			link_encoder,
			&link->mst_stream_alloc_table);
		break;
	case DP_128b_132b_ENCODING:
		hpo_dp_link_encoder->funcs->update_stream_allocation_table(
				hpo_dp_link_encoder,
				&link->mst_stream_alloc_table);
		break;
	case DP_UNKNOWN_ENCODING:
		DC_LOG_ERROR("Failure: unknown encoding format\n");
		return DC_ERROR_UNEXPECTED;
	}
#else
	link_encoder->funcs->update_mst_stream_allocation_table(
		link_encoder,
		&link->mst_stream_alloc_table);
#endif

	/* send down message */
	ret = dm_helpers_dp_mst_poll_for_allocation_change_trigger(
@@ -3469,13 +3519,191 @@ enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx)
	pbn = get_pbn_from_timing(pipe_ctx);
	avg_time_slots_per_mtp = dc_fixpt_div(pbn, pbn_per_slot);

#if defined(CONFIG_DRM_AMD_DC_DCN)
	switch (dp_get_link_encoding_format(&link->cur_link_settings)) {
	case DP_8b_10b_ENCODING:
		stream_encoder->funcs->set_throttled_vcp_size(
			stream_encoder,
			avg_time_slots_per_mtp);
		break;
	case DP_128b_132b_ENCODING:
		hpo_dp_link_encoder->funcs->set_throttled_vcp_size(
				hpo_dp_link_encoder,
				hpo_dp_stream_encoder->inst,
				avg_time_slots_per_mtp);
		break;
	case DP_UNKNOWN_ENCODING:
		DC_LOG_ERROR("Failure: unknown encoding format\n");
		return DC_ERROR_UNEXPECTED;
	}
#else
	stream_encoder->funcs->set_throttled_vcp_size(
		stream_encoder,
		avg_time_slots_per_mtp);
#endif

	return DC_OK;

}

#if defined(CONFIG_DRM_AMD_DC_DCN)
enum dc_status dc_link_reduce_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t bw_in_kbps)
{
	struct dc_stream_state *stream = pipe_ctx->stream;
	struct dc_link *link = stream->link;
	struct fixed31_32 avg_time_slots_per_mtp;
	struct fixed31_32 pbn;
	struct fixed31_32 pbn_per_slot;
	struct link_encoder *link_encoder = link->link_enc;
	struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc;
	struct dp_mst_stream_allocation_table proposed_table = {0};
	uint8_t i;
	enum act_return_status ret;
	DC_LOGGER_INIT(link->ctx->logger);

	/* decrease throttled vcp size */
	pbn_per_slot = get_pbn_per_slot(stream);
	pbn = get_pbn_from_bw_in_kbps(bw_in_kbps);
	avg_time_slots_per_mtp = dc_fixpt_div(pbn, pbn_per_slot);

	stream_encoder->funcs->set_throttled_vcp_size(
				stream_encoder,
				avg_time_slots_per_mtp);

	/* send ALLOCATE_PAYLOAD sideband message with updated pbn */
	dm_helpers_dp_mst_send_payload_allocation(
			stream->ctx,
			stream,
			true);

	/* notify immediate branch device table update */
	if (dm_helpers_dp_mst_write_payload_allocation_table(
			stream->ctx,
			stream,
			&proposed_table,
			true)) {
		/* update mst stream allocation table software state */
		update_mst_stream_alloc_table(
				link,
				pipe_ctx->stream_res.stream_enc,
				pipe_ctx->stream_res.hpo_dp_stream_enc,
				&proposed_table);
	} else {
		DC_LOG_WARNING("Failed to update"
				"MST allocation table for"
				"pipe idx:%d\n",
				pipe_ctx->pipe_idx);
	}

	DC_LOG_MST("%s  "
			"stream_count: %d: \n ",
			__func__,
			link->mst_stream_alloc_table.stream_count);

	for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
		DC_LOG_MST("stream_enc[%d]: %p      "
				"stream[%d].vcp_id: %d      "
				"stream[%d].slot_count: %d\n",
				i,
				(void *) link->mst_stream_alloc_table.stream_allocations[i].stream_enc,
				i,
				link->mst_stream_alloc_table.stream_allocations[i].vcp_id,
				i,
				link->mst_stream_alloc_table.stream_allocations[i].slot_count);
	}

	ASSERT(proposed_table.stream_count > 0);

	/* update mst stream allocation table hardware state */
	link_encoder->funcs->update_mst_stream_allocation_table(
			link_encoder,
			&link->mst_stream_alloc_table);

	/* poll for immediate branch device ACT handled */
	ret = dm_helpers_dp_mst_poll_for_allocation_change_trigger(
			stream->ctx,
			stream);

	return DC_OK;
}

enum dc_status dc_link_increase_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t bw_in_kbps)
{
	struct dc_stream_state *stream = pipe_ctx->stream;
	struct dc_link *link = stream->link;
	struct fixed31_32 avg_time_slots_per_mtp;
	struct fixed31_32 pbn;
	struct fixed31_32 pbn_per_slot;
	struct link_encoder *link_encoder = link->link_enc;
	struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc;
	struct dp_mst_stream_allocation_table proposed_table = {0};
	uint8_t i;
	enum act_return_status ret;
	DC_LOGGER_INIT(link->ctx->logger);

	/* notify immediate branch device table update */
	if (dm_helpers_dp_mst_write_payload_allocation_table(
				stream->ctx,
				stream,
				&proposed_table,
				true)) {
		/* update mst stream allocation table software state */
		update_mst_stream_alloc_table(
				link,
				pipe_ctx->stream_res.stream_enc,
				pipe_ctx->stream_res.hpo_dp_stream_enc,
				&proposed_table);
	}

	DC_LOG_MST("%s  "
			"stream_count: %d: \n ",
			__func__,
			link->mst_stream_alloc_table.stream_count);

	for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
		DC_LOG_MST("stream_enc[%d]: %p      "
				"stream[%d].vcp_id: %d      "
				"stream[%d].slot_count: %d\n",
				i,
				(void *) link->mst_stream_alloc_table.stream_allocations[i].stream_enc,
				i,
				link->mst_stream_alloc_table.stream_allocations[i].vcp_id,
				i,
				link->mst_stream_alloc_table.stream_allocations[i].slot_count);
	}

	ASSERT(proposed_table.stream_count > 0);

	/* update mst stream allocation table hardware state */
	link_encoder->funcs->update_mst_stream_allocation_table(
			link_encoder,
			&link->mst_stream_alloc_table);

	/* poll for immediate branch device ACT handled */
	ret = dm_helpers_dp_mst_poll_for_allocation_change_trigger(
			stream->ctx,
			stream);

	if (ret != ACT_LINK_LOST) {
		/* send ALLOCATE_PAYLOAD sideband message with updated pbn */
		dm_helpers_dp_mst_send_payload_allocation(
				stream->ctx,
				stream,
				true);
	}

	/* increase throttled vcp size */
	pbn = get_pbn_from_bw_in_kbps(bw_in_kbps);
	pbn_per_slot = get_pbn_per_slot(stream);
	avg_time_slots_per_mtp = dc_fixpt_div(pbn, pbn_per_slot);

	stream_encoder->funcs->set_throttled_vcp_size(
				stream_encoder,
				avg_time_slots_per_mtp);

	return DC_OK;
}
#endif

static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
{
@@ -3483,6 +3711,10 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
	struct dc_link *link = stream->link;
	struct link_encoder *link_encoder = NULL;
	struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc;
#if defined(CONFIG_DRM_AMD_DC_DCN)
	struct hpo_dp_link_encoder *hpo_dp_link_encoder = link->hpo_dp_link_enc;
	struct hpo_dp_stream_encoder *hpo_dp_stream_encoder = pipe_ctx->stream_res.hpo_dp_stream_enc;
#endif
	struct dp_mst_stream_allocation_table proposed_table = {0};
	struct fixed31_32 avg_time_slots_per_mtp = dc_fixpt_from_int(0);
	int i;
@@ -3504,9 +3736,28 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
	 */

	/* slot X.Y */
#if defined(CONFIG_DRM_AMD_DC_DCN)
	switch (dp_get_link_encoding_format(&link->cur_link_settings)) {
	case DP_8b_10b_ENCODING:
		stream_encoder->funcs->set_throttled_vcp_size(
			stream_encoder,
			avg_time_slots_per_mtp);
		break;
	case DP_128b_132b_ENCODING:
		hpo_dp_link_encoder->funcs->set_throttled_vcp_size(
				hpo_dp_link_encoder,
				hpo_dp_stream_encoder->inst,
				avg_time_slots_per_mtp);
		break;
	case DP_UNKNOWN_ENCODING:
		DC_LOG_ERROR("Failure: unknown encoding format\n");
		return DC_ERROR_UNEXPECTED;
	}
#else
	stream_encoder->funcs->set_throttled_vcp_size(
		stream_encoder,
		avg_time_slots_per_mtp);
#endif

	/* TODO: which component is responsible for remove payload table? */
	if (mst_mode) {
@@ -3516,8 +3767,16 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
				&proposed_table,
				false)) {

#if defined(CONFIG_DRM_AMD_DC_DCN)
			update_mst_stream_alloc_table(
						link,
						pipe_ctx->stream_res.stream_enc,
						pipe_ctx->stream_res.hpo_dp_stream_enc,
						&proposed_table);
#else
			update_mst_stream_alloc_table(
				link, pipe_ctx->stream_res.stream_enc, &proposed_table);
#endif
		}
		else {
				DC_LOG_WARNING("Failed to update"
@@ -3533,6 +3792,20 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
			link->mst_stream_alloc_table.stream_count);

	for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
#if defined(CONFIG_DRM_AMD_DC_DCN)
		DC_LOG_MST("stream_enc[%d]: %p      "
		"stream[%d].hpo_dp_stream_enc: %p      "
		"stream[%d].vcp_id: %d      "
		"stream[%d].slot_count: %d\n",
		i,
		(void *) link->mst_stream_alloc_table.stream_allocations[i].stream_enc,
		i,
		(void *) link->mst_stream_alloc_table.stream_allocations[i].hpo_dp_stream_enc,
		i,
		link->mst_stream_alloc_table.stream_allocations[i].vcp_id,
		i,
		link->mst_stream_alloc_table.stream_allocations[i].slot_count);
#else
		DC_LOG_MST("stream_enc[%d]: %p      "
		"stream[%d].vcp_id: %d      "
		"stream[%d].slot_count: %d\n",
@@ -3542,11 +3815,30 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
		link->mst_stream_alloc_table.stream_allocations[i].vcp_id,
		i,
		link->mst_stream_alloc_table.stream_allocations[i].slot_count);
#endif
	}

#if defined(CONFIG_DRM_AMD_DC_DCN)
	switch (dp_get_link_encoding_format(&link->cur_link_settings)) {
	case DP_8b_10b_ENCODING:
		link_encoder->funcs->update_mst_stream_allocation_table(
			link_encoder,
			&link->mst_stream_alloc_table);
		break;
	case DP_128b_132b_ENCODING:
		hpo_dp_link_encoder->funcs->update_stream_allocation_table(
				hpo_dp_link_encoder,
				&link->mst_stream_alloc_table);
		break;
	case DP_UNKNOWN_ENCODING:
		DC_LOG_ERROR("Failure: unknown encoding format\n");
		return DC_ERROR_UNEXPECTED;
	}
#else
	link_encoder->funcs->update_mst_stream_allocation_table(
		link_encoder,
		&link->mst_stream_alloc_table);
#endif

	if (mst_mode) {
		dm_helpers_dp_mst_poll_for_allocation_change_trigger(
Loading