From ddd580e8ff564c5d5f0b4fa941f8e64e365ea0d3 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Thu, 7 Jan 2016 15:06:08 -0500 Subject: [PATCH 0679/1110] drm/amd/dal: MST get stream hadle refact Signed-off-by: Hersen Wu Acked-by: Jordan Lazare --- .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dc_helpers.c | 94 ++++++------- drivers/gpu/drm/amd/dal/dc/core/dc_link.c | 147 +++++++++++++++------ drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c | 11 +- drivers/gpu/drm/amd/dal/dc/dc_helpers.h | 3 +- .../drm/amd/dal/dc/dce110/dce110_hw_sequencer.c | 2 + drivers/gpu/drm/amd/dal/dc/inc/core_types.h | 7 +- .../gpu/drm/amd/dal/include/link_service_types.h | 1 + 7 files changed, 167 insertions(+), 98 deletions(-) diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dc_helpers.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dc_helpers.c index 578517f..ff9b5c1 100644 --- a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dc_helpers.c +++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dc_helpers.c @@ -160,74 +160,73 @@ static struct amdgpu_connector *get_connector_for_link( return aconnector; } -static const struct dc_stream *get_stream_for_vcid( - struct drm_device *dev, - struct amdgpu_connector *master_port, - int vcid) +const struct dp_mst_stream_allocation *find_stream_with_matching_vcpi( + const struct dp_mst_stream_allocation_table *table, + uint32_t vcpi) { - struct drm_connector *connector; - struct amdgpu_connector *aconnector; - struct drm_crtc *crtc; - struct amdgpu_crtc *acrtc; - struct dc_target *dc_target; - - list_for_each_entry( - connector, - &dev->mode_config.connector_list, - head) { - - aconnector = to_amdgpu_connector(connector); - - /* Check whether mst connector */ - if (!aconnector->mst_port) - continue; - - /* Check whether same physical connector. */ - if (master_port != aconnector->mst_port) { - continue; - } + int i; - if (aconnector->port->vcpi.vcpi == vcid) { - crtc = aconnector->base.state->crtc; - acrtc = to_amdgpu_crtc(crtc); - dc_target = acrtc->target; - return dc_target->streams[0]; - } + for (i = 0; i < table->stream_count; i++) { + const struct dp_mst_stream_allocation *sa = + &table->stream_allocations[i]; + if (sa->vcp_id == vcpi) + return sa; } return NULL; } + static void get_payload_table( struct drm_device *dev, struct amdgpu_connector *aconnector, - struct dp_mst_stream_allocation_table *table) + const struct dc_stream *stream, + const struct dp_mst_stream_allocation_table *cur_table, + struct dp_mst_stream_allocation_table *proposed_table) { int i; - struct drm_dp_mst_topology_mgr *mst_mgr = &aconnector->mst_port->mst_mgr; - struct amdgpu_connector *master_port = aconnector->mst_port; + struct drm_dp_mst_topology_mgr *mst_mgr = + &aconnector->mst_port->mst_mgr; mutex_lock(&mst_mgr->payload_lock); + proposed_table->stream_count = 0; + /* number of active streams */ for (i = 0; i < mst_mgr->max_payloads; i++) { if (mst_mgr->payloads[i].num_slots == 0) - break; + break; /* end of vcp_id table */ + + ASSERT(mst_mgr->payloads[i].payload_state != + DP_PAYLOAD_DELETE_LOCAL); if (mst_mgr->payloads[i].payload_state == DP_PAYLOAD_LOCAL || - mst_mgr->payloads[i].payload_state == DP_PAYLOAD_REMOTE) { - table->stream_allocations[i].slot_count = mst_mgr->payloads[i].num_slots; - table->stream_allocations[i].stream = - get_stream_for_vcid( - dev, - master_port, - mst_mgr->payloads[i].vcpi); + mst_mgr->payloads[i].payload_state == + DP_PAYLOAD_REMOTE) { + + const struct dp_mst_stream_allocation *sa_src + = find_stream_with_matching_vcpi( + cur_table, + mst_mgr->proposed_vcpis[i]->vcpi); + + if (sa_src) { + proposed_table->stream_allocations[ + proposed_table->stream_count] = *sa_src; + proposed_table->stream_count++; + } else { + struct dp_mst_stream_allocation *sa = + &proposed_table->stream_allocations[ + proposed_table->stream_count]; + + sa->slot_count = + mst_mgr->payloads[i].num_slots; + sa->stream = stream; + sa->vcp_id = mst_mgr->proposed_vcpis[i]->vcpi; + proposed_table->stream_count++; + } } } - table->stream_count = i; - mutex_unlock(&mst_mgr->payload_lock); - } /* @@ -236,7 +235,8 @@ static void get_payload_table( bool dc_helpers_dp_mst_write_payload_allocation_table( struct dc_context *ctx, const struct dc_stream *stream, - struct dp_mst_stream_allocation_table *table, + const struct dp_mst_stream_allocation_table *cur_table, + struct dp_mst_stream_allocation_table *proposed_table, bool enable) { struct amdgpu_device *adev = ctx->driver_context; @@ -312,7 +312,7 @@ bool dc_helpers_dp_mst_write_payload_allocation_table( * stream. AMD ASIC stream slot allocation should follow the same * sequence. copy DRM MST allocation to dc */ - get_payload_table(dev, aconnector, table); + get_payload_table(dev, aconnector, stream, cur_table, proposed_table); if (ret) return false; diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_link.c b/drivers/gpu/drm/amd/dal/dc/core/dc_link.c index ac6785a..794465e 100644 --- a/drivers/gpu/drm/amd/dal/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/dal/dc/core/dc_link.c @@ -1106,18 +1106,6 @@ static enum dc_status enable_link_dp(struct core_stream *stream) static enum dc_status enable_link_dp_mst(struct core_stream *stream) { struct core_link *link = stream->sink->link; - bool already_enabled = false; - int i; - - for (i = 0; i < link->enabled_stream_count; i++) { - if (link->enabled_streams[i] == stream) - already_enabled = true; - } - - if (!already_enabled && link->enabled_stream_count < MAX_SINKS_PER_LINK) - link->enabled_streams[link->enabled_stream_count++] = stream; - else if (link->enabled_stream_count >= MAX_SINKS_PER_LINK) - return DC_ERROR_UNEXPECTED; /* sink signal type after MST branch is MST. Multiple MST sinks * share one link. Link DP PHY is enable or training only once. @@ -1285,9 +1273,12 @@ void core_link_resume(struct core_link *link) static struct fixed31_32 get_pbn_per_slot(struct core_stream *stream) { - struct link_settings *link_settings = &stream->sink->link->cur_link_settings; - uint32_t link_rate_in_mbps = link_settings->link_rate * LINK_RATE_REF_FREQ_IN_MHZ; - struct fixed31_32 mbps = dal_fixed31_32_from_int(link_rate_in_mbps * link_settings->lane_count); + struct link_settings *link_settings = + &stream->sink->link->cur_link_settings; + uint32_t link_rate_in_mbps = + link_settings->link_rate * LINK_RATE_REF_FREQ_IN_MHZ; + struct fixed31_32 mbps = dal_fixed31_32_from_int( + link_rate_in_mbps * link_settings->lane_count); return dal_fixed31_32_div_int(mbps, 54); } @@ -1318,15 +1309,13 @@ static struct fixed31_32 get_pbn_from_timing(struct core_stream *stream) /* * margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006 - * * The unit of 54/64Mbytes/sec is an arbitrary unit chosen based on * common multiplier to render an integer PBN for all link rate/lane * counts combinations - * * * calculate - * peak_kbps *= (1006/1000) - * peak_kbps *= (64/54) - * peak_kbps *= 8 convert to bytes + * peak_kbps *= (1006/1000) + * peak_kbps *= (64/54) + * peak_kbps *= 8 convert to bytes */ numerator = 64 * PEAK_FACTOR_X1000; @@ -1342,11 +1331,12 @@ static enum dc_status allocate_mst_payload(struct core_stream *stream) struct core_link *link = stream->sink->link; struct link_encoder *link_encoder = link->link_enc; struct stream_encoder *stream_encoder = stream->stream_enc; - struct dp_mst_stream_allocation_table table = {0}; + struct dp_mst_stream_allocation_table proposed_table = {0}; struct fixed31_32 avg_time_slots_per_mtp; struct dc *dc = stream->ctx->dc; struct fixed31_32 pbn; struct fixed31_32 pbn_per_slot; + uint8_t i; /* enable_link_dp_mst already check link->enabled_stream_count * and stream is in link->stream[]. This is called during set mode, @@ -1357,22 +1347,53 @@ static enum dc_status allocate_mst_payload(struct core_stream *stream) dc_helpers_dp_mst_write_payload_allocation_table( stream->ctx, &stream->public, - &table, + &link->stream_alloc_table, + &proposed_table, true); + dal_logger_write(link->ctx->logger, + LOG_MAJOR_MST, + LOG_MINOR_MST_PROGRAMMING, + "%s " + "stream_count: %d: \n ", + __func__, + proposed_table.stream_count); + + for (i = 0; i < MAX_CONTROLLER_NUM; i++) { + dal_logger_write(link->ctx->logger, + LOG_MAJOR_MST, + LOG_MINOR_MST_PROGRAMMING, + "stream[%d]: 0x%x " + "stream[%d].vcp_id: %d " + "stream[%d].slot_count: %d\n", + i, + proposed_table.stream_allocations[i].stream, + i, + proposed_table.stream_allocations[i].vcp_id, + i, + proposed_table.stream_allocations[i].slot_count); + } + + ASSERT(proposed_table.stream_count > 0); + ASSERT(proposed_table.stream_count - + link->stream_alloc_table.stream_count == 1); + /* * temporary fix. Unplug of MST chain happened (two displays), * table is empty on first reset mode, and cause 0 division in * avg_time_slots_per_mtp calculation */ - if (table.stream_count == 0) + /* to be removed or debugged */ + if (proposed_table.stream_count == 0) return DC_OK; /* program DP source TX for payload */ dc->hwss.update_mst_stream_allocation_table( link_encoder, - &table); + &proposed_table); + + link->stream_alloc_table = proposed_table; /* send down message */ dc_helpers_dp_mst_poll_for_allocation_change_trigger( @@ -1384,10 +1405,12 @@ static enum dc_status allocate_mst_payload(struct core_stream *stream) &stream->public, true); + /* slot X.Y for only current stream */ pbn_per_slot = get_pbn_per_slot(stream); pbn = get_pbn_from_timing(stream); avg_time_slots_per_mtp = dal_fixed31_32_div(pbn, pbn_per_slot); + dc->hwss.set_mst_bandwidth( stream_encoder, avg_time_slots_per_mtp); @@ -1401,10 +1424,10 @@ static enum dc_status deallocate_mst_payload(struct core_stream *stream) struct core_link *link = stream->sink->link; struct link_encoder *link_encoder = link->link_enc; struct stream_encoder *stream_encoder = stream->stream_enc; - struct dp_mst_stream_allocation_table table = {0}; + struct dp_mst_stream_allocation_table proposed_table = {0}; struct fixed31_32 avg_time_slots_per_mtp = dal_fixed31_32_from_int(0); - uint8_t i; struct dc *dc = stream->ctx->dc; + uint8_t i; /* deallocate_mst_payload is called before disable link. When mode or * disable/enable monitor, new stream is created which is not in link @@ -1412,16 +1435,6 @@ static enum dc_status deallocate_mst_payload(struct core_stream *stream) * should not done. For new mode set, map_resources will get engine * for new stream, so stream_enc->id should be validated until here. */ - if (link->enabled_stream_count == 0) - return DC_OK; - - for (i = 0; i < link->enabled_stream_count; i++) { - if (link->enabled_streams[i] == stream) - break; - } - /* stream is not in link stream list */ - if (i == link->enabled_stream_count) - return DC_OK; /* slot X.Y */ dc->hwss.set_mst_bandwidth( @@ -1432,12 +1445,41 @@ static enum dc_status deallocate_mst_payload(struct core_stream *stream) dc_helpers_dp_mst_write_payload_allocation_table( stream->ctx, &stream->public, - &table, + &link->stream_alloc_table, + &proposed_table, false); + dal_logger_write(link->ctx->logger, + LOG_MAJOR_MST, + LOG_MINOR_MST_PROGRAMMING, + "%s" + "stream_count: %d: ", + __func__, + proposed_table.stream_count); + + for (i = 0; i < MAX_CONTROLLER_NUM; i++) { + dal_logger_write(link->ctx->logger, + LOG_MAJOR_MST, + LOG_MINOR_MST_PROGRAMMING, + "stream[%d]: 0x%x" + "stream[%d].vcp_id: %d" + "stream[%d].slot_count: %d", + i, + proposed_table.stream_allocations[i].stream, + i, + proposed_table.stream_allocations[i].vcp_id, + i, + proposed_table.stream_allocations[i].slot_count); + } + + ASSERT(link->stream_alloc_table.stream_count - + proposed_table.stream_count == 1); + dc->hwss.update_mst_stream_allocation_table( link_encoder, - &table); + &proposed_table); + + link->stream_alloc_table = proposed_table; dc_helpers_dp_mst_poll_for_allocation_change_trigger( stream->ctx, @@ -1482,3 +1524,32 @@ void core_link_disable_stream( disable_link(stream); } + +void core_link_update_stream( + struct core_link *link, + struct core_stream *stream) +{ + if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { + uint32_t i; + + for (i = 0; i < link->stream_alloc_table.stream_count; i++) { + const struct core_stream *s; + + s = DC_STREAM_TO_CORE( + link->stream_alloc_table. + stream_allocations[i].stream); + + if (stream->stream_enc == s->stream_enc) { + link->stream_alloc_table.stream_allocations[i].stream = + &stream->public; + + dal_logger_write(link->ctx->logger, + LOG_MAJOR_MST, + LOG_MINOR_MST_PROGRAMMING, + "%s ", + __func__); + break; + } + } + } +} diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c index 1356238..27acac8 100644 --- a/drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c @@ -84,17 +84,8 @@ void dp_disable_link_phy(struct core_link *link, enum signal_type signal) void dp_disable_link_phy_mst(struct core_link *link, struct core_stream *stream) { - int i, j; - - for (i = 0; i < link->enabled_stream_count; i++) { - if (link->enabled_streams[i] == stream) { - link->enabled_stream_count--; - for (j = i; j < link->enabled_stream_count; j++) - link->enabled_streams[j] = link->enabled_streams[j+1]; - } - } /* MST disable link only when no stream use the link */ - if (link->enabled_stream_count > 0) + if (link->stream_alloc_table.stream_count > 0) return; dp_disable_link_phy(link, stream->signal); diff --git a/drivers/gpu/drm/amd/dal/dc/dc_helpers.h b/drivers/gpu/drm/amd/dal/dc/dc_helpers.h index d96e907..b4c338a 100644 --- a/drivers/gpu/drm/amd/dal/dc/dc_helpers.h +++ b/drivers/gpu/drm/amd/dal/dc/dc_helpers.h @@ -44,7 +44,8 @@ enum dc_edid_status dc_helpers_parse_edid_caps( bool dc_helpers_dp_mst_write_payload_allocation_table( struct dc_context *ctx, const struct dc_stream *stream, - struct dp_mst_stream_allocation_table *table, + const struct dp_mst_stream_allocation_table *cur_table, + struct dp_mst_stream_allocation_table *proposed_table, bool enable); /* diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c index 1085137..685301b 100644 --- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c @@ -900,6 +900,8 @@ static enum dc_status apply_single_controller_ctx_to_hw(uint8_t controller_idx, if (timing_changed) { core_link_enable_stream(stream->sink->link, stream); + } else { + core_link_update_stream(stream->sink->link, stream); } if (dc_is_dp_signal(stream->signal)) diff --git a/drivers/gpu/drm/amd/dal/dc/inc/core_types.h b/drivers/gpu/drm/amd/dal/dc/inc/core_types.h index 2b97d4d..5f918c1 100644 --- a/drivers/gpu/drm/amd/dal/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/dal/dc/inc/core_types.h @@ -224,8 +224,7 @@ struct core_link { union dp_wa dp_wa; /* MST record stream using this link */ - const struct core_stream *enabled_streams[MAX_SINKS_PER_LINK]; - uint8_t enabled_stream_count; + struct dp_mst_stream_allocation_table stream_alloc_table; }; #define DC_LINK_TO_LINK(dc_link) container_of(dc_link, struct core_link, public) @@ -248,6 +247,10 @@ void core_link_disable_stream( struct core_link *link, struct core_stream *stream); +void core_link_update_stream( + struct core_link *link, + struct core_stream *stream); + /********** DAL Core*********************/ #include "display_clock_interface.h" diff --git a/drivers/gpu/drm/amd/dal/include/link_service_types.h b/drivers/gpu/drm/amd/dal/include/link_service_types.h index 429d969..573dd5c 100644 --- a/drivers/gpu/drm/amd/dal/include/link_service_types.h +++ b/drivers/gpu/drm/amd/dal/include/link_service_types.h @@ -393,6 +393,7 @@ struct mst_device_info { struct dp_mst_stream_allocation { /* stream engine id (DIG) */ const struct dc_stream *stream; + uint32_t vcp_id; /* number of slots required for the DP stream in * transport packet */ uint32_t slot_count; -- 2.7.4