[PATCH 3/4] drm/amd/display: Add DP 2.0 MST DC Support
Alex Deucher
alexdeucher at gmail.com
Wed Oct 20 19:55:54 UTC 2021
On Wed, Oct 20, 2021 at 3:50 PM Bhawanpreet Lakha
<Bhawanpreet.Lakha at amd.com> wrote:
>
> From: Fangzhi Zuo <Jerry.Zuo at amd.com>
Please include a patch description.
Alex
>
> Signed-off-by: Fangzhi Zuo <Jerry.Zuo at amd.com>
> ---
> drivers/gpu/drm/amd/display/dc/core/dc.c | 14 +
> drivers/gpu/drm/amd/display/dc/core/dc_link.c | 280 ++++++++++++++++++
> .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 19 ++
> drivers/gpu/drm/amd/display/dc/dc_link.h | 7 +
> drivers/gpu/drm/amd/display/dc/dc_stream.h | 13 +
> 5 files changed, 333 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
> index 8be04be19124..935a50d6e933 100644
> --- a/drivers/gpu/drm/amd/display/dc/core/dc.c
> +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
> @@ -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,
> diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
> index e5d6cbd7ea78..b23972b6a27c 100644
> --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
> +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
> @@ -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,30 @@ 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;
> + }
> +#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 +3516,188 @@ 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;
> + }
> +#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 +3705,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 +3730,25 @@ 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;
> + }
> +#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 +3758,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 +3783,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 +3806,27 @@ 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;
> + }
> +#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(
> diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
> index 296b0defcd1c..bb96e4e9ccfc 100644
> --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
> +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
> @@ -5993,6 +5993,25 @@ enum dp_link_encoding dp_get_link_encoding_format(const struct dc_link_settings
> }
>
> #if defined(CONFIG_DRM_AMD_DC_DCN)
> +enum dp_link_encoding dc_link_dp_mst_decide_link_encoding_format(const struct dc_link *link)
> +{
> + struct dc_link_settings link_settings = {0};
> +
> + if (!dc_is_dp_signal(link->connector_signal))
> + return DP_UNKNOWN_ENCODING;
> +
> + if (link->preferred_link_setting.lane_count !=
> + LANE_COUNT_UNKNOWN &&
> + link->preferred_link_setting.link_rate !=
> + LINK_RATE_UNKNOWN) {
> + link_settings = link->preferred_link_setting;
> + } else {
> + decide_mst_link_settings(link, &link_settings);
> + }
> +
> + return dp_get_link_encoding_format(&link_settings);
> +}
> +
> // TODO - DP2.0 Link: Fix get_lane_status to handle LTTPR offset (SST and MST)
> static void get_lane_status(
> struct dc_link *link,
> diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h
> index a73d64b1fd33..08815310d85b 100644
> --- a/drivers/gpu/drm/amd/display/dc/dc_link.h
> +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h
> @@ -295,6 +295,10 @@ enum dc_detect_reason {
> bool dc_link_detect(struct dc_link *dc_link, enum dc_detect_reason reason);
> bool dc_link_get_hpd_state(struct dc_link *dc_link);
> enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx);
> +#if defined(CONFIG_DRM_AMD_DC_DCN)
> +enum dc_status dc_link_reduce_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t req_pbn);
> +enum dc_status dc_link_increase_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t req_pbn);
> +#endif
>
> /* Notify DC about DP RX Interrupt (aka Short Pulse Interrupt).
> * Return:
> @@ -424,4 +428,7 @@ uint32_t dc_bandwidth_in_kbps_from_timing(
> bool dc_link_is_fec_supported(const struct dc_link *link);
> bool dc_link_should_enable_fec(const struct dc_link *link);
>
> +#if defined(CONFIG_DRM_AMD_DC_DCN)
> +enum dp_link_encoding dc_link_dp_mst_decide_link_encoding_format(const struct dc_link *link);
> +#endif
> #endif /* DC_LINK_H_ */
> diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h
> index b8ebc1f09538..e37c4a10bfd5 100644
> --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h
> +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h
> @@ -115,6 +115,13 @@ struct periodic_interrupt_config {
> int lines_offset;
> };
>
> +#if defined(CONFIG_DRM_AMD_DC_DCN)
> +struct dc_mst_stream_bw_update {
> + bool is_increase; // is bandwidth reduced or increased
> + uint32_t mst_stream_bw; // new mst bandwidth in kbps
> +};
> +#endif
> +
> union stream_update_flags {
> struct {
> uint32_t scaling:1;
> @@ -125,6 +132,9 @@ union stream_update_flags {
> uint32_t gamut_remap:1;
> uint32_t wb_update:1;
> uint32_t dsc_changed : 1;
> +#if defined(CONFIG_DRM_AMD_DC_DCN)
> + uint32_t mst_bw : 1;
> +#endif
> } bits;
>
> uint32_t raw;
> @@ -278,6 +288,9 @@ struct dc_stream_update {
>
> struct dc_writeback_update *wb_update;
> struct dc_dsc_config *dsc_config;
> +#if defined(CONFIG_DRM_AMD_DC_DCN)
> + struct dc_mst_stream_bw_update *mst_bw_update;
> +#endif
> struct dc_transfer_func *func_shaper;
> struct dc_3dlut *lut3d_func;
>
> --
> 2.25.1
>
More information about the dri-devel
mailing list