| |
@@ -1,2478 +0,0 @@
|
| |
- From 7c4fed4d2afd27d7acb8835f8e79f49c99c03cdf Mon Sep 17 00:00:00 2001
|
| |
- From: Wayne Lin <Wayne.Lin@amd.com>
|
| |
- Date: Thu, 12 Jan 2023 16:50:44 +0800
|
| |
- Subject: [PATCH 3/3] Revert "drm/display/dp_mst: Move all payload info into
|
| |
- the atomic state"
|
| |
- MIME-Version: 1.0
|
| |
- Content-Type: text/plain; charset=UTF-8
|
| |
- Content-Transfer-Encoding: 8bit
|
| |
-
|
| |
- This reverts commit 4d07b0bc403403438d9cf88450506240c5faf92f.
|
| |
-
|
| |
- [Why]
|
| |
- Changes cause regression on amdgpu mst.
|
| |
- E.g.
|
| |
- In fill_dc_mst_payload_table_from_drm(), amdgpu expects to add/remove payload
|
| |
- one by one and call fill_dc_mst_payload_table_from_drm() to update the HW
|
| |
- maintained payload table. But previous change tries to go through all the
|
| |
- payloads in mst_state and update amdpug hw maintained table in once everytime
|
| |
- driver only tries to add/remove a specific payload stream only. The newly
|
| |
- design idea conflicts with the implementation in amdgpu nowadays.
|
| |
-
|
| |
- [How]
|
| |
- Revert this patch first. After addressing all regression problems caused by
|
| |
- this previous patch, will add it back and adjust it.
|
| |
-
|
| |
- Signed-off-by: Wayne Lin <Wayne.Lin@amd.com>
|
| |
- Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2171
|
| |
- Cc: stable@vger.kernel.org # 6.1
|
| |
- Cc: Lyude Paul <lyude@redhat.com>
|
| |
- Cc: Harry Wentland <harry.wentland@amd.com>
|
| |
- Cc: Mario Limonciello <mario.limonciello@amd.com>
|
| |
- Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
|
| |
- Cc: Ben Skeggs <bskeggs@redhat.com>
|
| |
- Cc: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
|
| |
- Cc: Fangzhi Zuo <Jerry.Zuo@amd.com>
|
| |
- ---
|
| |
- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 53 +-
|
| |
- .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 104 ++-
|
| |
- .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 87 ++-
|
| |
- .../amd/display/include/link_service_types.h | 3 -
|
| |
- drivers/gpu/drm/display/drm_dp_mst_topology.c | 724 ++++++++++++------
|
| |
- drivers/gpu/drm/i915/display/intel_dp_mst.c | 64 +-
|
| |
- drivers/gpu/drm/i915/display/intel_hdcp.c | 24 +-
|
| |
- drivers/gpu/drm/nouveau/dispnv50/disp.c | 169 ++--
|
| |
- include/drm/display/drm_dp_mst_helper.h | 178 +++--
|
| |
- 9 files changed, 876 insertions(+), 530 deletions(-)
|
| |
-
|
| |
- diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
| |
- index dacad8b85963..40defd664b49 100644
|
| |
- --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
| |
- +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
| |
- @@ -6460,7 +6460,6 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
|
| |
- const struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
|
| |
- struct drm_dp_mst_topology_mgr *mst_mgr;
|
| |
- struct drm_dp_mst_port *mst_port;
|
| |
- - struct drm_dp_mst_topology_state *mst_state;
|
| |
- enum dc_color_depth color_depth;
|
| |
- int clock, bpp = 0;
|
| |
- bool is_y420 = false;
|
| |
- @@ -6474,13 +6473,6 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
|
| |
- if (!crtc_state->connectors_changed && !crtc_state->mode_changed)
|
| |
- return 0;
|
| |
-
|
| |
- - mst_state = drm_atomic_get_mst_topology_state(state, mst_mgr);
|
| |
- - if (IS_ERR(mst_state))
|
| |
- - return PTR_ERR(mst_state);
|
| |
- -
|
| |
- - if (!mst_state->pbn_div)
|
| |
- - mst_state->pbn_div = dm_mst_get_pbn_divider(aconnector->mst_port->dc_link);
|
| |
- -
|
| |
- if (!state->duplicated) {
|
| |
- int max_bpc = conn_state->max_requested_bpc;
|
| |
- is_y420 = drm_mode_is_420_also(&connector->display_info, adjusted_mode) &&
|
| |
- @@ -6492,10 +6484,11 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
|
| |
- clock = adjusted_mode->clock;
|
| |
- dm_new_connector_state->pbn = drm_dp_calc_pbn_mode(clock, bpp, false);
|
| |
- }
|
| |
- -
|
| |
- - dm_new_connector_state->vcpi_slots =
|
| |
- - drm_dp_atomic_find_time_slots(state, mst_mgr, mst_port,
|
| |
- - dm_new_connector_state->pbn);
|
| |
- + dm_new_connector_state->vcpi_slots = drm_dp_atomic_find_time_slots(state,
|
| |
- + mst_mgr,
|
| |
- + mst_port,
|
| |
- + dm_new_connector_state->pbn,
|
| |
- + dm_mst_get_pbn_divider(aconnector->dc_link));
|
| |
- if (dm_new_connector_state->vcpi_slots < 0) {
|
| |
- DRM_DEBUG_ATOMIC("failed finding vcpi slots: %d\n", (int)dm_new_connector_state->vcpi_slots);
|
| |
- return dm_new_connector_state->vcpi_slots;
|
| |
- @@ -6566,14 +6559,17 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
|
| |
- dm_conn_state->vcpi_slots = slot_num;
|
| |
-
|
| |
- ret = drm_dp_mst_atomic_enable_dsc(state, aconnector->port,
|
| |
- - dm_conn_state->pbn, false);
|
| |
- + dm_conn_state->pbn, 0, false);
|
| |
- if (ret < 0)
|
| |
- return ret;
|
| |
-
|
| |
- continue;
|
| |
- }
|
| |
-
|
| |
- - vcpi = drm_dp_mst_atomic_enable_dsc(state, aconnector->port, pbn, true);
|
| |
- + vcpi = drm_dp_mst_atomic_enable_dsc(state,
|
| |
- + aconnector->port,
|
| |
- + pbn, pbn_div,
|
| |
- + true);
|
| |
- if (vcpi < 0)
|
| |
- return vcpi;
|
| |
-
|
| |
- @@ -9407,6 +9403,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
|
| |
- struct dm_crtc_state *dm_old_crtc_state, *dm_new_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);
|
| |
- @@ -9654,6 +9652,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
|
| |
- diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
|
| |
- index f72c013d3a5b..c8f9d10fde17 100644
|
| |
- --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
|
| |
- +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
|
| |
- @@ -27,7 +27,6 @@
|
| |
- #include <linux/acpi.h>
|
| |
- #include <linux/i2c.h>
|
| |
-
|
| |
- -#include <drm/drm_atomic.h>
|
| |
- #include <drm/drm_probe_helper.h>
|
| |
- #include <drm/amdgpu_drm.h>
|
| |
- #include <drm/drm_edid.h>
|
| |
- @@ -120,27 +119,40 @@ enum dc_edid_status dm_helpers_parse_edid_caps(
|
| |
- }
|
| |
-
|
| |
- static void
|
| |
- -fill_dc_mst_payload_table_from_drm(struct drm_dp_mst_topology_state *mst_state,
|
| |
- - struct amdgpu_dm_connector *aconnector,
|
| |
- - struct dc_dp_mst_stream_allocation_table *table)
|
| |
- +fill_dc_mst_payload_table_from_drm(struct amdgpu_dm_connector *aconnector,
|
| |
- + struct dc_dp_mst_stream_allocation_table *proposed_table)
|
| |
- {
|
| |
- - struct dc_dp_mst_stream_allocation_table new_table = { 0 };
|
| |
- - struct dc_dp_mst_stream_allocation *sa;
|
| |
- - struct drm_dp_mst_atomic_payload *payload;
|
| |
- -
|
| |
- - /* Fill payload info*/
|
| |
- - list_for_each_entry(payload, &mst_state->payloads, next) {
|
| |
- - if (payload->delete)
|
| |
- - continue;
|
| |
- -
|
| |
- - sa = &new_table.stream_allocations[new_table.stream_count];
|
| |
- - sa->slot_count = payload->time_slots;
|
| |
- - sa->vcp_id = payload->vcpi;
|
| |
- - new_table.stream_count++;
|
| |
- + int i;
|
| |
- + 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; /* 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) {
|
| |
- +
|
| |
- + struct dc_dp_mst_stream_allocation *sa =
|
| |
- + &proposed_table->stream_allocations[
|
| |
- + proposed_table->stream_count];
|
| |
- +
|
| |
- + sa->slot_count = mst_mgr->payloads[i].num_slots;
|
| |
- + sa->vcp_id = mst_mgr->proposed_vcpis[i]->vcpi;
|
| |
- + proposed_table->stream_count++;
|
| |
- + }
|
| |
- }
|
| |
-
|
| |
- - /* Overwrite the old table */
|
| |
- - *table = new_table;
|
| |
- + mutex_unlock(&mst_mgr->payload_lock);
|
| |
- }
|
| |
-
|
| |
- void dm_helpers_dp_update_branch_info(
|
| |
- @@ -158,9 +170,11 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
|
| |
- bool enable)
|
| |
- {
|
| |
- struct amdgpu_dm_connector *aconnector;
|
| |
- - struct drm_dp_mst_topology_state *mst_state;
|
| |
- - struct drm_dp_mst_atomic_payload *payload;
|
| |
- + struct dm_connector_state *dm_conn_state;
|
| |
- 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
|
| |
- @@ -171,21 +185,40 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
|
| |
- if (!aconnector || !aconnector->mst_port)
|
| |
- return false;
|
| |
-
|
| |
- + dm_conn_state = to_dm_connector_state(aconnector->base.state);
|
| |
- +
|
| |
- mst_mgr = &aconnector->mst_port->mst_mgr;
|
| |
- - mst_state = to_drm_dp_mst_topology_state(mst_mgr->base.state);
|
| |
- +
|
| |
- + if (!mst_mgr->mst_state)
|
| |
- + return false;
|
| |
- +
|
| |
- + 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,
|
| |
- + dm_conn_state->pbn,
|
| |
- + dm_conn_state->vcpi_slots);
|
| |
- + if (!ret)
|
| |
- + return false;
|
| |
- +
|
| |
- + } else {
|
| |
- + drm_dp_mst_reset_vcpi_slots(mst_mgr, mst_port);
|
| |
- + }
|
| |
-
|
| |
- /* It's OK for this to fail */
|
| |
- - payload = drm_atomic_get_mst_payload_state(mst_state, aconnector->port);
|
| |
- - if (enable)
|
| |
- - drm_dp_add_payload_part1(mst_mgr, mst_state, payload);
|
| |
- - else
|
| |
- - drm_dp_remove_payload(mst_mgr, mst_state, payload);
|
| |
- + 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
|
| |
- * stream. AMD ASIC stream slot allocation should follow the same
|
| |
- * sequence. copy DRM MST allocation to dc */
|
| |
- - fill_dc_mst_payload_table_from_drm(mst_state, aconnector, proposed_table);
|
| |
- +
|
| |
- + fill_dc_mst_payload_table_from_drm(aconnector, proposed_table);
|
| |
-
|
| |
- return true;
|
| |
- }
|
| |
- @@ -242,9 +275,8 @@ bool dm_helpers_dp_mst_send_payload_allocation(
|
| |
- bool enable)
|
| |
- {
|
| |
- struct amdgpu_dm_connector *aconnector;
|
| |
- - struct drm_dp_mst_topology_state *mst_state;
|
| |
- struct drm_dp_mst_topology_mgr *mst_mgr;
|
| |
- - struct drm_dp_mst_atomic_payload *payload;
|
| |
- + struct drm_dp_mst_port *mst_port;
|
| |
- enum mst_progress_status set_flag = MST_ALLOCATE_NEW_PAYLOAD;
|
| |
- enum mst_progress_status clr_flag = MST_CLEAR_ALLOCATED_PAYLOAD;
|
| |
-
|
| |
- @@ -253,16 +285,19 @@ bool dm_helpers_dp_mst_send_payload_allocation(
|
| |
- if (!aconnector || !aconnector->mst_port)
|
| |
- return false;
|
| |
-
|
| |
- + mst_port = aconnector->port;
|
| |
- +
|
| |
- mst_mgr = &aconnector->mst_port->mst_mgr;
|
| |
- - mst_state = to_drm_dp_mst_topology_state(mst_mgr->base.state);
|
| |
-
|
| |
- - payload = drm_atomic_get_mst_payload_state(mst_state, aconnector->port);
|
| |
- + if (!mst_mgr->mst_state)
|
| |
- + return false;
|
| |
- +
|
| |
- if (!enable) {
|
| |
- set_flag = MST_CLEAR_ALLOCATED_PAYLOAD;
|
| |
- clr_flag = MST_ALLOCATE_NEW_PAYLOAD;
|
| |
- }
|
| |
-
|
| |
- - if (enable && drm_dp_add_payload_part2(mst_mgr, mst_state->base.state, payload)) {
|
| |
- + if (drm_dp_update_payload_part2(mst_mgr)) {
|
| |
- amdgpu_dm_set_mst_status(&aconnector->mst_status,
|
| |
- set_flag, false);
|
| |
- } else {
|
| |
- @@ -272,6 +307,9 @@ bool dm_helpers_dp_mst_send_payload_allocation(
|
| |
- clr_flag, false);
|
| |
- }
|
| |
-
|
| |
- + if (!enable)
|
| |
- + drm_dp_mst_deallocate_vcpi(mst_mgr, mst_port);
|
| |
- +
|
| |
- return true;
|
| |
- }
|
| |
-
|
| |
- diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
|
| |
- index 6483ba266893..d57f1528a295 100644
|
| |
- --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
|
| |
- +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
|
| |
- @@ -598,8 +598,15 @@ void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm,
|
| |
-
|
| |
- dc_link_dp_get_max_link_enc_cap(aconnector->dc_link, &max_link_enc_cap);
|
| |
- aconnector->mst_mgr.cbs = &dm_mst_cbs;
|
| |
- - drm_dp_mst_topology_mgr_init(&aconnector->mst_mgr, adev_to_drm(dm->adev),
|
| |
- - &aconnector->dm_dp_aux.aux, 16, 4, aconnector->connector_id);
|
| |
- + drm_dp_mst_topology_mgr_init(
|
| |
- + &aconnector->mst_mgr,
|
| |
- + adev_to_drm(dm->adev),
|
| |
- + &aconnector->dm_dp_aux.aux,
|
| |
- + 16,
|
| |
- + 4,
|
| |
- + max_link_enc_cap.lane_count,
|
| |
- + drm_dp_bw_code_to_link_rate(max_link_enc_cap.link_rate),
|
| |
- + aconnector->connector_id);
|
| |
-
|
| |
- drm_connector_attach_dp_subconnector_property(&aconnector->base);
|
| |
- }
|
| |
- @@ -703,13 +710,12 @@ static int bpp_x16_from_pbn(struct dsc_mst_fairness_params param, int pbn)
|
| |
- return dsc_config.bits_per_pixel;
|
| |
- }
|
| |
-
|
| |
- -static int increase_dsc_bpp(struct drm_atomic_state *state,
|
| |
- - struct drm_dp_mst_topology_state *mst_state,
|
| |
- - struct dc_link *dc_link,
|
| |
- - struct dsc_mst_fairness_params *params,
|
| |
- - struct dsc_mst_fairness_vars *vars,
|
| |
- - int count,
|
| |
- - int k)
|
| |
- +static bool increase_dsc_bpp(struct drm_atomic_state *state,
|
| |
- + struct dc_link *dc_link,
|
| |
- + struct dsc_mst_fairness_params *params,
|
| |
- + struct dsc_mst_fairness_vars *vars,
|
| |
- + int count,
|
| |
- + int k)
|
| |
- {
|
| |
- int i;
|
| |
- bool bpp_increased[MAX_PIPES];
|
| |
- @@ -717,10 +723,13 @@ static int increase_dsc_bpp(struct drm_atomic_state *state,
|
| |
- int min_initial_slack;
|
| |
- int next_index;
|
| |
- int remaining_to_increase = 0;
|
| |
- + int pbn_per_timeslot;
|
| |
- int link_timeslots_used;
|
| |
- int fair_pbn_alloc;
|
| |
- int ret = 0;
|
| |
-
|
| |
- + pbn_per_timeslot = dm_mst_get_pbn_divider(dc_link);
|
| |
- +
|
| |
- for (i = 0; i < count; i++) {
|
| |
- if (vars[i + k].dsc_enabled) {
|
| |
- initial_slack[i] =
|
| |
- @@ -751,17 +760,18 @@ static int increase_dsc_bpp(struct drm_atomic_state *state,
|
| |
- link_timeslots_used = 0;
|
| |
-
|
| |
- for (i = 0; i < count; i++)
|
| |
- - link_timeslots_used += DIV_ROUND_UP(vars[i + k].pbn, mst_state->pbn_div);
|
| |
- + link_timeslots_used += DIV_ROUND_UP(vars[i + k].pbn, pbn_per_timeslot);
|
| |
-
|
| |
- - fair_pbn_alloc =
|
| |
- - (63 - link_timeslots_used) / remaining_to_increase * mst_state->pbn_div;
|
| |
- + fair_pbn_alloc = (63 - link_timeslots_used) / remaining_to_increase * pbn_per_timeslot;
|
| |
-
|
| |
- if (initial_slack[next_index] > fair_pbn_alloc) {
|
| |
- vars[next_index].pbn += fair_pbn_alloc;
|
| |
- +
|
| |
- ret = drm_dp_atomic_find_time_slots(state,
|
| |
- params[next_index].port->mgr,
|
| |
- params[next_index].port,
|
| |
- - vars[next_index].pbn);
|
| |
- + vars[next_index].pbn,
|
| |
- + pbn_per_timeslot);
|
| |
- if (ret < 0)
|
| |
- return ret;
|
| |
-
|
| |
- @@ -773,7 +783,8 @@ static int increase_dsc_bpp(struct drm_atomic_state *state,
|
| |
- ret = drm_dp_atomic_find_time_slots(state,
|
| |
- params[next_index].port->mgr,
|
| |
- params[next_index].port,
|
| |
- - vars[next_index].pbn);
|
| |
- + vars[next_index].pbn,
|
| |
- + pbn_per_timeslot);
|
| |
- if (ret < 0)
|
| |
- return ret;
|
| |
- }
|
| |
- @@ -782,7 +793,8 @@ static int increase_dsc_bpp(struct drm_atomic_state *state,
|
| |
- ret = drm_dp_atomic_find_time_slots(state,
|
| |
- params[next_index].port->mgr,
|
| |
- params[next_index].port,
|
| |
- - vars[next_index].pbn);
|
| |
- + vars[next_index].pbn,
|
| |
- + pbn_per_timeslot);
|
| |
- if (ret < 0)
|
| |
- return ret;
|
| |
-
|
| |
- @@ -794,7 +806,8 @@ static int increase_dsc_bpp(struct drm_atomic_state *state,
|
| |
- ret = drm_dp_atomic_find_time_slots(state,
|
| |
- params[next_index].port->mgr,
|
| |
- params[next_index].port,
|
| |
- - vars[next_index].pbn);
|
| |
- + vars[next_index].pbn,
|
| |
- + pbn_per_timeslot);
|
| |
- if (ret < 0)
|
| |
- return ret;
|
| |
- }
|
| |
- @@ -850,10 +863,12 @@ static int try_disable_dsc(struct drm_atomic_state *state,
|
| |
- break;
|
| |
-
|
| |
- vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
|
| |
- +
|
| |
- ret = drm_dp_atomic_find_time_slots(state,
|
| |
- params[next_index].port->mgr,
|
| |
- params[next_index].port,
|
| |
- - vars[next_index].pbn);
|
| |
- + vars[next_index].pbn,
|
| |
- + dm_mst_get_pbn_divider(dc_link));
|
| |
- if (ret < 0)
|
| |
- return ret;
|
| |
-
|
| |
- @@ -863,10 +878,12 @@ static int try_disable_dsc(struct drm_atomic_state *state,
|
| |
- vars[next_index].bpp_x16 = 0;
|
| |
- } else {
|
| |
- vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
|
| |
- +
|
| |
- ret = drm_dp_atomic_find_time_slots(state,
|
| |
- params[next_index].port->mgr,
|
| |
- params[next_index].port,
|
| |
- - vars[next_index].pbn);
|
| |
- + vars[next_index].pbn,
|
| |
- + dm_mst_get_pbn_divider(dc_link));
|
| |
- if (ret < 0)
|
| |
- return ret;
|
| |
- }
|
| |
- @@ -877,31 +894,21 @@ static int try_disable_dsc(struct drm_atomic_state *state,
|
| |
- return 0;
|
| |
- }
|
| |
-
|
| |
- -static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
|
| |
- - struct dc_state *dc_state,
|
| |
- - struct dc_link *dc_link,
|
| |
- - struct dsc_mst_fairness_vars *vars,
|
| |
- - struct drm_dp_mst_topology_mgr *mgr,
|
| |
- - int *link_vars_start_index)
|
| |
- +static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
|
| |
- + struct dc_state *dc_state,
|
| |
- + struct dc_link *dc_link,
|
| |
- + struct dsc_mst_fairness_vars *vars,
|
| |
- + int *link_vars_start_index)
|
| |
- {
|
| |
- + int i, k, ret;
|
| |
- struct dc_stream_state *stream;
|
| |
- struct dsc_mst_fairness_params params[MAX_PIPES];
|
| |
- struct amdgpu_dm_connector *aconnector;
|
| |
- - struct drm_dp_mst_topology_state *mst_state = drm_atomic_get_mst_topology_state(state, mgr);
|
| |
- int count = 0;
|
| |
- - int i, k, ret;
|
| |
- bool debugfs_overwrite = false;
|
| |
-
|
| |
- memset(params, 0, sizeof(params));
|
| |
-
|
| |
- - if (IS_ERR(mst_state))
|
| |
- - return PTR_ERR(mst_state);
|
| |
- -
|
| |
- - mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);
|
| |
- -#if defined(CONFIG_DRM_AMD_DC_DCN)
|
| |
- - drm_dp_mst_update_slots(mst_state, dc_link_dp_mst_decide_link_encoding_format(dc_link));
|
| |
- -#endif
|
| |
- -
|
| |
- /* Set up params */
|
| |
- for (i = 0; i < dc_state->stream_count; i++) {
|
| |
- struct dc_dsc_policy dsc_policy = {0};
|
| |
- @@ -961,7 +968,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
|
| |
- vars[i + k].dsc_enabled = false;
|
| |
- vars[i + k].bpp_x16 = 0;
|
| |
- ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port,
|
| |
- - vars[i + k].pbn);
|
| |
- + vars[i + k].pbn, dm_mst_get_pbn_divider(dc_link));
|
| |
- if (ret < 0)
|
| |
- return ret;
|
| |
- }
|
| |
- @@ -980,7 +987,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
|
| |
- vars[i + k].dsc_enabled = true;
|
| |
- vars[i + k].bpp_x16 = params[i].bw_range.min_target_bpp_x16;
|
| |
- ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
|
| |
- - params[i].port, vars[i + k].pbn);
|
| |
- + params[i].port, vars[i + k].pbn, dm_mst_get_pbn_divider(dc_link));
|
| |
- if (ret < 0)
|
| |
- return ret;
|
| |
- } else {
|
| |
- @@ -988,7 +995,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
|
| |
- vars[i + k].dsc_enabled = false;
|
| |
- vars[i + k].bpp_x16 = 0;
|
| |
- ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
|
| |
- - params[i].port, vars[i + k].pbn);
|
| |
- + params[i].port, vars[i + k].pbn, dm_mst_get_pbn_divider(dc_link));
|
| |
- if (ret < 0)
|
| |
- return ret;
|
| |
- }
|
| |
- @@ -998,7 +1005,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
|
| |
- return ret;
|
| |
-
|
| |
- /* Optimize degree of compression */
|
| |
- - ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars, count, k);
|
| |
- + ret = increase_dsc_bpp(state, dc_link, params, vars, count, k);
|
| |
- if (ret < 0)
|
| |
- return ret;
|
| |
-
|
| |
- @@ -1148,7 +1155,7 @@ int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
|
| |
- continue;
|
| |
-
|
| |
- mst_mgr = aconnector->port->mgr;
|
| |
- - ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars, mst_mgr,
|
| |
- + ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
|
| |
- &link_vars_start_index);
|
| |
- if (ret != 0)
|
| |
- return ret;
|
| |
- @@ -1206,7 +1213,7 @@ static int pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
|
| |
- continue;
|
| |
-
|
| |
- mst_mgr = aconnector->port->mgr;
|
| |
- - ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars, mst_mgr,
|
| |
- + ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
|
| |
- &link_vars_start_index);
|
| |
- if (ret != 0)
|
| |
- return ret;
|
| |
- diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h
|
| |
- index d1e91d31d151..0889c2a86733 100644
|
| |
- --- a/drivers/gpu/drm/amd/display/include/link_service_types.h
|
| |
- +++ b/drivers/gpu/drm/amd/display/include/link_service_types.h
|
| |
- @@ -252,9 +252,6 @@ union dpcd_training_lane_set {
|
| |
- * _ONLY_ be filled out from DM and then passed to DC, do NOT use these for _any_ kind of atomic
|
| |
- * state calculations in DM, or you will break something.
|
| |
- */
|
| |
- -
|
| |
- -struct drm_dp_mst_port;
|
| |
- -
|
| |
- /* DP MST stream allocation (payload bandwidth number) */
|
| |
- struct dc_dp_mst_stream_allocation {
|
| |
- uint8_t vcp_id;
|
| |
- diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
|
| |
- index 51a46689cda7..95ff57d20216 100644
|
| |
- --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
|
| |
- +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
|
| |
- @@ -68,7 +68,8 @@ static bool dump_dp_payload_table(struct drm_dp_mst_topology_mgr *mgr,
|
| |
- static void drm_dp_mst_topology_put_port(struct drm_dp_mst_port *port);
|
| |
-
|
| |
- static int drm_dp_dpcd_write_payload(struct drm_dp_mst_topology_mgr *mgr,
|
| |
- - int id, u8 start_slot, u8 num_slots);
|
| |
- + int id,
|
| |
- + struct drm_dp_payload *payload);
|
| |
-
|
| |
- static int drm_dp_send_dpcd_read(struct drm_dp_mst_topology_mgr *mgr,
|
| |
- struct drm_dp_mst_port *port,
|
| |
- @@ -1234,6 +1235,57 @@ build_query_stream_enc_status(struct drm_dp_sideband_msg_tx *msg, u8 stream_id,
|
| |
- return 0;
|
| |
- }
|
| |
-
|
| |
- +static int drm_dp_mst_assign_payload_id(struct drm_dp_mst_topology_mgr *mgr,
|
| |
- + struct drm_dp_vcpi *vcpi)
|
| |
- +{
|
| |
- + int ret, vcpi_ret;
|
| |
- +
|
| |
- + mutex_lock(&mgr->payload_lock);
|
| |
- + ret = find_first_zero_bit(&mgr->payload_mask, mgr->max_payloads + 1);
|
| |
- + if (ret > mgr->max_payloads) {
|
| |
- + ret = -EINVAL;
|
| |
- + drm_dbg_kms(mgr->dev, "out of payload ids %d\n", ret);
|
| |
- + goto out_unlock;
|
| |
- + }
|
| |
- +
|
| |
- + vcpi_ret = find_first_zero_bit(&mgr->vcpi_mask, mgr->max_payloads + 1);
|
| |
- + if (vcpi_ret > mgr->max_payloads) {
|
| |
- + ret = -EINVAL;
|
| |
- + drm_dbg_kms(mgr->dev, "out of vcpi ids %d\n", ret);
|
| |
- + goto out_unlock;
|
| |
- + }
|
| |
- +
|
| |
- + set_bit(ret, &mgr->payload_mask);
|
| |
- + set_bit(vcpi_ret, &mgr->vcpi_mask);
|
| |
- + vcpi->vcpi = vcpi_ret + 1;
|
| |
- + mgr->proposed_vcpis[ret - 1] = vcpi;
|
| |
- +out_unlock:
|
| |
- + mutex_unlock(&mgr->payload_lock);
|
| |
- + return ret;
|
| |
- +}
|
| |
- +
|
| |
- +static void drm_dp_mst_put_payload_id(struct drm_dp_mst_topology_mgr *mgr,
|
| |
- + int vcpi)
|
| |
- +{
|
| |
- + int i;
|
| |
- +
|
| |
- + if (vcpi == 0)
|
| |
- + return;
|
| |
- +
|
| |
- + mutex_lock(&mgr->payload_lock);
|
| |
- + drm_dbg_kms(mgr->dev, "putting payload %d\n", vcpi);
|
| |
- + clear_bit(vcpi - 1, &mgr->vcpi_mask);
|
| |
- +
|
| |
- + for (i = 0; i < mgr->max_payloads; i++) {
|
| |
- + if (mgr->proposed_vcpis[i] &&
|
| |
- + mgr->proposed_vcpis[i]->vcpi == vcpi) {
|
| |
- + mgr->proposed_vcpis[i] = NULL;
|
| |
- + clear_bit(i + 1, &mgr->payload_mask);
|
| |
- + }
|
| |
- + }
|
| |
- + mutex_unlock(&mgr->payload_lock);
|
| |
- +}
|
| |
- +
|
| |
- static bool check_txmsg_state(struct drm_dp_mst_topology_mgr *mgr,
|
| |
- struct drm_dp_sideband_msg_tx *txmsg)
|
| |
- {
|
| |
- @@ -1686,7 +1738,7 @@ drm_dp_mst_dump_port_topology_history(struct drm_dp_mst_port *port) {}
|
| |
- #define save_port_topology_ref(port, type)
|
| |
- #endif
|
| |
-
|
| |
- -struct drm_dp_mst_atomic_payload *
|
| |
- +static struct drm_dp_mst_atomic_payload *
|
| |
- drm_atomic_get_mst_payload_state(struct drm_dp_mst_topology_state *state,
|
| |
- struct drm_dp_mst_port *port)
|
| |
- {
|
| |
- @@ -1698,7 +1750,6 @@ drm_atomic_get_mst_payload_state(struct drm_dp_mst_topology_state *state,
|
| |
-
|
| |
- return NULL;
|
| |
- }
|
| |
- -EXPORT_SYMBOL(drm_atomic_get_mst_payload_state);
|
| |
-
|
| |
- static void drm_dp_destroy_mst_branch_device(struct kref *kref)
|
| |
- {
|
| |
- @@ -3201,8 +3252,6 @@ int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr,
|
| |
- struct drm_dp_mst_port *port,
|
| |
- struct drm_dp_query_stream_enc_status_ack_reply *status)
|
| |
- {
|
| |
- - struct drm_dp_mst_topology_state *state;
|
| |
- - struct drm_dp_mst_atomic_payload *payload;
|
| |
- struct drm_dp_sideband_msg_tx *txmsg;
|
| |
- u8 nonce[7];
|
| |
- int ret;
|
| |
- @@ -3219,10 +3268,6 @@ int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr,
|
| |
-
|
| |
- get_random_bytes(nonce, sizeof(nonce));
|
| |
-
|
| |
- - drm_modeset_lock(&mgr->base.lock, NULL);
|
| |
- - state = to_drm_dp_mst_topology_state(mgr->base.state);
|
| |
- - payload = drm_atomic_get_mst_payload_state(state, port);
|
| |
- -
|
| |
- /*
|
| |
- * "Source device targets the QUERY_STREAM_ENCRYPTION_STATUS message
|
| |
- * transaction at the MST Branch device directly connected to the
|
| |
- @@ -3230,7 +3275,7 @@ int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr,
|
| |
- */
|
| |
- txmsg->dst = mgr->mst_primary;
|
| |
-
|
| |
- - build_query_stream_enc_status(txmsg, payload->vcpi, nonce);
|
| |
- + build_query_stream_enc_status(txmsg, port->vcpi.vcpi, nonce);
|
| |
-
|
| |
- drm_dp_queue_down_tx(mgr, txmsg);
|
| |
-
|
| |
- @@ -3247,7 +3292,6 @@ int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr,
|
| |
- memcpy(status, &txmsg->reply.u.enc_status, sizeof(*status));
|
| |
-
|
| |
- out:
|
| |
- - drm_modeset_unlock(&mgr->base.lock);
|
| |
- drm_dp_mst_topology_put_port(port);
|
| |
- out_get_port:
|
| |
- kfree(txmsg);
|
| |
- @@ -3256,162 +3300,238 @@ int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr,
|
| |
- EXPORT_SYMBOL(drm_dp_send_query_stream_enc_status);
|
| |
-
|
| |
- static int drm_dp_create_payload_step1(struct drm_dp_mst_topology_mgr *mgr,
|
| |
- - struct drm_dp_mst_atomic_payload *payload)
|
| |
- + int id,
|
| |
- + struct drm_dp_payload *payload)
|
| |
- {
|
| |
- - return drm_dp_dpcd_write_payload(mgr, payload->vcpi, payload->vc_start_slot,
|
| |
- - payload->time_slots);
|
| |
- + int ret;
|
| |
- +
|
| |
- + ret = drm_dp_dpcd_write_payload(mgr, id, payload);
|
| |
- + if (ret < 0) {
|
| |
- + payload->payload_state = 0;
|
| |
- + return ret;
|
| |
- + }
|
| |
- + payload->payload_state = DP_PAYLOAD_LOCAL;
|
| |
- + return 0;
|
| |
- }
|
| |
-
|
| |
- static int drm_dp_create_payload_step2(struct drm_dp_mst_topology_mgr *mgr,
|
| |
- - struct drm_dp_mst_atomic_payload *payload)
|
| |
- + struct drm_dp_mst_port *port,
|
| |
- + int id,
|
| |
- + struct drm_dp_payload *payload)
|
| |
- {
|
| |
- int ret;
|
| |
- - struct drm_dp_mst_port *port = drm_dp_mst_topology_get_port_validated(mgr, payload->port);
|
| |
- -
|
| |
- - if (!port)
|
| |
- - return -EIO;
|
| |
-
|
| |
- - ret = drm_dp_payload_send_msg(mgr, port, payload->vcpi, payload->pbn);
|
| |
- - drm_dp_mst_topology_put_port(port);
|
| |
- + ret = drm_dp_payload_send_msg(mgr, port, id, port->vcpi.pbn);
|
| |
- + if (ret < 0)
|
| |
- + return ret;
|
| |
- + payload->payload_state = DP_PAYLOAD_REMOTE;
|
| |
- return ret;
|
| |
- }
|
| |
-
|
| |
- static int drm_dp_destroy_payload_step1(struct drm_dp_mst_topology_mgr *mgr,
|
| |
- - struct drm_dp_mst_topology_state *mst_state,
|
| |
- - struct drm_dp_mst_atomic_payload *payload)
|
| |
- + struct drm_dp_mst_port *port,
|
| |
- + int id,
|
| |
- + struct drm_dp_payload *payload)
|
| |
- {
|
| |
- drm_dbg_kms(mgr->dev, "\n");
|
| |
- -
|
| |
- /* it's okay for these to fail */
|
| |
- - drm_dp_payload_send_msg(mgr, payload->port, payload->vcpi, 0);
|
| |
- - drm_dp_dpcd_write_payload(mgr, payload->vcpi, payload->vc_start_slot, 0);
|
| |
- + if (port) {
|
| |
- + drm_dp_payload_send_msg(mgr, port, id, 0);
|
| |
- + }
|
| |
-
|
| |
- + drm_dp_dpcd_write_payload(mgr, id, payload);
|
| |
- + payload->payload_state = DP_PAYLOAD_DELETE_LOCAL;
|
| |
- + return 0;
|
| |
- +}
|
| |
- +
|
| |
- +static int drm_dp_destroy_payload_step2(struct drm_dp_mst_topology_mgr *mgr,
|
| |
- + int id,
|
| |
- + struct drm_dp_payload *payload)
|
| |
- +{
|
| |
- + payload->payload_state = 0;
|
| |
- return 0;
|
| |
- }
|
| |
-
|
| |
- /**
|
| |
- - * drm_dp_add_payload_part1() - Execute payload update part 1
|
| |
- - * @mgr: Manager to use.
|
| |
- - * @mst_state: The MST atomic state
|
| |
- - * @payload: The payload to write
|
| |
- + * drm_dp_update_payload_part1() - Execute payload update part 1
|
| |
- + * @mgr: manager to use.
|
| |
- + * @start_slot: this is the cur slot
|
| |
- + *
|
| |
- + * NOTE: start_slot is a temporary workaround for non-atomic drivers,
|
| |
- + * this will be removed when non-atomic mst helpers are moved out of the helper
|
| |
- *
|
| |
- - * Determines the starting time slot for the given payload, and programs the VCPI for this payload
|
| |
- - * into hardware. After calling this, the driver should generate ACT and payload packets.
|
| |
- + * This iterates over all proposed virtual channels, and tries to
|
| |
- + * allocate space in the link for them. For 0->slots transitions,
|
| |
- + * this step just writes the VCPI to the MST device. For slots->0
|
| |
- + * transitions, this writes the updated VCPIs and removes the
|
| |
- + * remote VC payloads.
|
| |
- *
|
| |
- - * Returns: 0 on success, error code on failure. In the event that this fails,
|
| |
- - * @payload.vc_start_slot will also be set to -1.
|
| |
- + * after calling this the driver should generate ACT and payload
|
| |
- + * packets.
|
| |
- */
|
| |
- -int drm_dp_add_payload_part1(struct drm_dp_mst_topology_mgr *mgr,
|
| |
- - struct drm_dp_mst_topology_state *mst_state,
|
| |
- - struct drm_dp_mst_atomic_payload *payload)
|
| |
- +int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr, int start_slot)
|
| |
- {
|
| |
- + struct drm_dp_payload req_payload;
|
| |
- struct drm_dp_mst_port *port;
|
| |
- - int ret;
|
| |
- + int i, j;
|
| |
- + int cur_slots = start_slot;
|
| |
- + bool skip;
|
| |
-
|
| |
- - port = drm_dp_mst_topology_get_port_validated(mgr, payload->port);
|
| |
- - if (!port)
|
| |
- - return 0;
|
| |
- + mutex_lock(&mgr->payload_lock);
|
| |
- + for (i = 0; i < mgr->max_payloads; i++) {
|
| |
- + struct drm_dp_vcpi *vcpi = mgr->proposed_vcpis[i];
|
| |
- + struct drm_dp_payload *payload = &mgr->payloads[i];
|
| |
- + bool put_port = false;
|
| |
-
|
| |
- - if (mgr->payload_count == 0)
|
| |
- - mgr->next_start_slot = mst_state->start_slot;
|
| |
- + /* solve the current payloads - compare to the hw ones
|
| |
- + - update the hw view */
|
| |
- + req_payload.start_slot = cur_slots;
|
| |
- + if (vcpi) {
|
| |
- + port = container_of(vcpi, struct drm_dp_mst_port,
|
| |
- + vcpi);
|
| |
-
|
| |
- - payload->vc_start_slot = mgr->next_start_slot;
|
| |
- + mutex_lock(&mgr->lock);
|
| |
- + skip = !drm_dp_mst_port_downstream_of_branch(port, mgr->mst_primary);
|
| |
- + mutex_unlock(&mgr->lock);
|
| |
-
|
| |
- - ret = drm_dp_create_payload_step1(mgr, payload);
|
| |
- - drm_dp_mst_topology_put_port(port);
|
| |
- - if (ret < 0) {
|
| |
- - drm_warn(mgr->dev, "Failed to create MST payload for port %p: %d\n",
|
| |
- - payload->port, ret);
|
| |
- - payload->vc_start_slot = -1;
|
| |
- - return ret;
|
| |
- - }
|
| |
- + if (skip) {
|
| |
- + drm_dbg_kms(mgr->dev,
|
| |