Message ID | 20211021151535.81769-1-Bhawanpreet.Lakha@amd.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | None | expand |
[Public] Hi Bhawan, It looks good to me. Thanks! Reviewed-by: Wayne Lin <Wayne.Lin@amd.com> Regards, Wayne > -----Original Message----- > From: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> > Sent: Thursday, October 21, 2021 11:16 PM > To: Zuo, Jerry <Jerry.Zuo@amd.com>; dri-devel@lists.freedesktop.org; lyude@redhat.com > Cc: intel-gfx@lists.freedesktop.org; Wentland, Harry <Harry.Wentland@amd.com>; Lin, Wayne <Wayne.Lin@amd.com>; Kazlauskas, > Nicholas <Nicholas.Kazlauskas@amd.com>; Lipski, Mikita <Mikita.Lipski@amd.com>; Lakha, Bhawanpreet > <Bhawanpreet.Lakha@amd.com> > Subject: [PATCH 3/4] drm/amd/display: Add DP 2.0 MST DC Support > > From: Fangzhi Zuo <Jerry.Zuo@amd.com> > > [Why] > configure/call DC interface for DP2 mst support. This is needed to make DP2 mst work. > > [How] > - add encoding type, logging, mst update/reduce payload functions > > Use the link encoding to determine the DP type (1.4 or 2.0) and add a flag to dc_stream_update to determine whether to increase/reduce > payloads. > > v2: > * add DP_UNKNOWN_ENCODING handling > > Signed-off-by: Fangzhi Zuo <Jerry.Zuo@amd.com> > Signed-off-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> > --- > drivers/gpu/drm/amd/display/dc/core/dc.c | 14 + > drivers/gpu/drm/amd/display/dc/core/dc_link.c | 292 ++++++++++++++++++ .../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, 345 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..ec5f107bc85a 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,23 +3447,56 @@ 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", > + 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); > +#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( > 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
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..ec5f107bc85a 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,23 +3447,56 @@ 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", + 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); +#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( 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;