diff options
Diffstat (limited to 'common/recipes-kernel/linux/files/0679-drm-amd-dal-MST-get-stream-hadle-refact.patch')
-rw-r--r-- | common/recipes-kernel/linux/files/0679-drm-amd-dal-MST-get-stream-hadle-refact.patch | 498 |
1 files changed, 498 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/files/0679-drm-amd-dal-MST-get-stream-hadle-refact.patch b/common/recipes-kernel/linux/files/0679-drm-amd-dal-MST-get-stream-hadle-refact.patch new file mode 100644 index 00000000..6a6c82bf --- /dev/null +++ b/common/recipes-kernel/linux/files/0679-drm-amd-dal-MST-get-stream-hadle-refact.patch @@ -0,0 +1,498 @@ +From ddd580e8ff564c5d5f0b4fa941f8e64e365ea0d3 Mon Sep 17 00:00:00 2001 +From: Hersen Wu <hersenxs.wu@amd.com> +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 <hersenxs.wu@amd.com> +Acked-by: Jordan Lazare <Jordan.Lazare@amd.com> +--- + .../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 + |