]> Git Repo - J-linux.git/commitdiff
Merge tag 'amd-drm-next-6.3-2023-01-27' of https://gitlab.freedesktop.org/agd5f/linux...
authorDave Airlie <[email protected]>
Mon, 30 Jan 2023 05:37:55 +0000 (15:37 +1000)
committerDave Airlie <[email protected]>
Mon, 30 Jan 2023 05:37:57 +0000 (15:37 +1000)
amd-drm-next-6.3-2023-01-27:

amdgpu:
- GC11 fixes
- SMU13 fixes
- Freesync fixes
- DP MST fixes
- DP MST code rework and cleanup
- AV1 fixes for VCN4
- DCN 3.2.x fixes
- PSR fixes
- DML optimizations
- DC link code rework

Signed-off-by: Dave Airlie <[email protected]>
From: Alex Deucher <[email protected]>
Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1  2 
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/display/drm_dp_mst_topology.c
include/drm/drm_print.h

index 1257745fb202384a2ecb1986fbf824dd7e3b9fe6,036657162cf4ddc8830a539953f2953842c285e5..5bee3ff623442e925cdf3c775598d1fb2a998791
@@@ -38,7 -38,6 +38,7 @@@
  
  #include <drm/drm_aperture.h>
  #include <drm/drm_atomic_helper.h>
 +#include <drm/drm_crtc_helper.h>
  #include <drm/drm_fb_helper.h>
  #include <drm/drm_probe_helper.h>
  #include <drm/amdgpu_drm.h>
@@@ -3038,6 -3037,18 +3038,18 @@@ static int amdgpu_device_ip_suspend_pha
                    (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SDMA))
                        continue;
  
+               /* Once swPSP provides the IMU, RLC FW binaries to TOS during cold-boot.
+                * These are in TMR, hence are expected to be reused by PSP-TOS to reload
+                * from this location and RLC Autoload automatically also gets loaded
+                * from here based on PMFW -> PSP message during re-init sequence.
+                * Therefore, the psp suspend & resume should be skipped to avoid destroy
+                * the TMR and reload FWs again for IMU enabled APU ASICs.
+                */
+               if (amdgpu_in_reset(adev) &&
+                   (adev->flags & AMD_IS_APU) && adev->gfx.imu.funcs &&
+                   adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP)
+                       continue;
                /* XXX handle errors */
                r = adev->ip_blocks[i].version->funcs->suspend(adev);
                /* XXX handle errors */
@@@ -3996,8 -4007,10 +4008,8 @@@ void amdgpu_device_fini_hw(struct amdgp
        }
        amdgpu_fence_driver_hw_fini(adev);
  
 -      if (adev->mman.initialized) {
 -              flush_delayed_work(&adev->mman.bdev.wq);
 -              ttm_bo_lock_delayed_workqueue(&adev->mman.bdev);
 -      }
 +      if (adev->mman.initialized)
 +              drain_workqueue(adev->mman.bdev.wq);
  
        if (adev->pm_sysfs_en)
                amdgpu_pm_sysfs_fini(adev);
index 44c57f4a84c45c81e17eb1514f1afb9b0deeaa84,b8633df418d436685106e23ee6b4462dda53f424..32fe05c810c6fcd3b89fe89ce7eba88f69c12aaf
@@@ -35,6 -35,7 +35,6 @@@
  #include <drm/drm_edid.h>
  #include <drm/drm_encoder.h>
  #include <drm/drm_fixed.h>
 -#include <drm/drm_crtc_helper.h>
  #include <drm/drm_framebuffer.h>
  #include <drm/drm_probe_helper.h>
  #include <linux/i2c.h>
@@@ -549,8 -550,8 +549,8 @@@ struct amdgpu_mst_connector 
  
        struct drm_dp_mst_topology_mgr mst_mgr;
        struct amdgpu_dm_dp_aux dm_dp_aux;
-       struct drm_dp_mst_port *port;
-       struct amdgpu_connector *mst_port;
+       struct drm_dp_mst_port *mst_output_port;
+       struct amdgpu_connector *mst_root;
        bool is_mst_connector;
        struct amdgpu_encoder *mst_encoder;
  };
index 8e4b668faa359b3e5cf8461fa981afc431d426ca,2e16b9e42ff1ac30d3a6f1d0574ceeed3787dd0b..e1d63826927a85c9cadfb21db3ad970a8e667273
@@@ -28,7 -28,6 +28,6 @@@
  
  #include "dm_services_types.h"
  #include "dc.h"
- #include "dc_link_dp.h"
  #include "link_enc_cfg.h"
  #include "dc/inc/core_types.h"
  #include "dal_asic_id.h"
@@@ -39,6 -38,9 +38,9 @@@
  #include "dc/dc_edid_parser.h"
  #include "dc/dc_stat.h"
  #include "amdgpu_dm_trace.h"
+ #include "dpcd_defs.h"
+ #include "link/protocols/link_dpcd.h"
+ #include "link_service_types.h"
  
  #include "vid.h"
  #include "amdgpu.h"
@@@ -66,7 -68,6 +68,7 @@@
  
  #include "ivsrcid/ivsrcid_vislands30.h"
  
 +#include <linux/backlight.h>
  #include <linux/module.h>
  #include <linux/moduleparam.h>
  #include <linux/types.h>
@@@ -1225,10 -1226,25 +1227,25 @@@ static void mmhub_read_system_context(s
        pa_config->gart_config.page_table_end_addr = page_table_end.quad_part << 12;
        pa_config->gart_config.page_table_base_addr = page_table_base.quad_part;
  
-       pa_config->is_hvm_enabled = 0;
+       pa_config->is_hvm_enabled = adev->mode_info.gpu_vm_support;
  
  }
  
+ static void force_connector_state(
+       struct amdgpu_dm_connector *aconnector,
+       enum drm_connector_force force_state)
+ {
+       struct drm_connector *connector = &aconnector->base;
+       mutex_lock(&connector->dev->mode_config.mutex);
+       aconnector->base.force = force_state;
+       mutex_unlock(&connector->dev->mode_config.mutex);
+       mutex_lock(&aconnector->hpd_lock);
+       drm_kms_helper_connector_hotplug_event(connector);
+       mutex_unlock(&aconnector->hpd_lock);
+ }
  static void dm_handle_hpd_rx_offload_work(struct work_struct *work)
  {
        struct hpd_rx_irq_offload_work *offload_work;
        struct amdgpu_device *adev;
        enum dc_connection_type new_connection_type = dc_connection_none;
        unsigned long flags;
+       union test_response test_response;
+       memset(&test_response, 0, sizeof(test_response));
  
        offload_work = container_of(work, struct hpd_rx_irq_offload_work, work);
        aconnector = offload_work->offload_wq->aconnector;
                goto skip;
  
        mutex_lock(&adev->dm.dc_lock);
-       if (offload_work->data.bytes.device_service_irq.bits.AUTOMATED_TEST)
+       if (offload_work->data.bytes.device_service_irq.bits.AUTOMATED_TEST) {
                dc_link_dp_handle_automated_test(dc_link);
+               if (aconnector->timing_changed) {
+                       /* force connector disconnect and reconnect */
+                       force_connector_state(aconnector, DRM_FORCE_OFF);
+                       msleep(100);
+                       force_connector_state(aconnector, DRM_FORCE_UNSPECIFIED);
+               }
+               test_response.bits.ACK = 1;
+               core_link_write_dpcd(
+               dc_link,
+               DP_TEST_RESPONSE,
+               &test_response.raw,
+               sizeof(test_response));
+       }
        else if ((dc_link->connector_signal != SIGNAL_TYPE_EDP) &&
-                       hpd_rx_irq_check_link_loss_status(dc_link, &offload_work->data) &&
+                       dc_link_check_link_loss_status(dc_link, &offload_work->data) &&
                        dc_link_dp_allow_hpd_rx_irq(dc_link)) {
                dc_link_dp_handle_link_loss(dc_link);
                spin_lock_irqsave(&offload_work->offload_wq->offload_lock, flags);
@@@ -2197,7 -2232,7 +2233,7 @@@ static void s3_handle_mst(struct drm_de
        drm_for_each_connector_iter(connector, &iter) {
                aconnector = to_amdgpu_dm_connector(connector);
                if (aconnector->dc_link->type != dc_connection_mst_branch ||
-                   aconnector->mst_port)
+                   aconnector->mst_root)
                        continue;
  
                mgr = &aconnector->mst_mgr;
@@@ -2987,6 -3022,10 +3023,10 @@@ void amdgpu_dm_update_connector_after_d
                                                    aconnector->edid);
                }
  
+               aconnector->timing_requested = kzalloc(sizeof(struct dc_crtc_timing), GFP_KERNEL);
+               if (!aconnector->timing_requested)
+                       dm_error("%s: failed to create aconnector->requested_timing\n", __func__);
                drm_connector_update_edid_property(connector, aconnector->edid);
                amdgpu_dm_update_freesync_caps(connector, aconnector->edid);
                update_connector_ext_caps(aconnector);
                dc_sink_release(aconnector->dc_sink);
                aconnector->dc_sink = NULL;
                aconnector->edid = NULL;
+               kfree(aconnector->timing_requested);
+               aconnector->timing_requested = NULL;
  #ifdef CONFIG_DRM_AMD_DC_HDCP
                /* Set CP to DESIRED if it was ENABLED, so we can re-enable it again on hotplug */
                if (connector->state->content_protection == DRM_MODE_CONTENT_PROTECTION_ENABLED)
@@@ -3042,6 -3083,8 +3084,8 @@@ static void handle_hpd_irq_helper(struc
        if (aconnector->fake_enable)
                aconnector->fake_enable = false;
  
+       aconnector->timing_changed = false;
        if (!dc_link_detect_sink(aconnector->dc_link, &new_connection_type))
                DRM_ERROR("KMS: Failed to detect connector\n");
  
@@@ -4327,10 -4370,6 +4371,10 @@@ static int amdgpu_dm_initialize_drm_dev
                amdgpu_set_panel_orientation(&aconnector->base);
        }
  
 +      /* If we didn't find a panel, notify the acpi video detection */
 +      if (dm->adev->flags & AMD_IS_APU && dm->num_of_edps == 0)
 +              acpi_video_report_nolcd();
 +
        /* Software is initialized. Now we can register interrupt handlers. */
        switch (adev->asic_type) {
  #if defined(CONFIG_DRM_AMD_DC_SI)
@@@ -5888,6 -5927,14 +5932,14 @@@ create_stream_for_sink(struct amdgpu_dm
                        stream, &mode, &aconnector->base, con_state, old_stream,
                        requested_bpc);
  
+       if (aconnector->timing_changed) {
+               DC_LOG_DEBUG("%s: overriding timing for automated test, bpc %d, changing to %d\n",
+                               __func__,
+                               stream->timing.display_color_depth,
+                               aconnector->timing_requested->display_color_depth);
+               stream->timing = *aconnector->timing_requested;
+       }
  #if defined(CONFIG_DRM_AMD_DC_DCN)
        /* SST DSC determination policy */
        update_dsc_caps(aconnector, sink, stream, &dsc_caps);
@@@ -6580,11 -6627,11 +6632,11 @@@ static int dm_encoder_helper_atomic_che
        int clock, bpp = 0;
        bool is_y420 = false;
  
-       if (!aconnector->port || !aconnector->dc_sink)
+       if (!aconnector->mst_output_port || !aconnector->dc_sink)
                return 0;
  
-       mst_port = aconnector->port;
-       mst_mgr = &aconnector->mst_port->mst_mgr;
+       mst_port = aconnector->mst_output_port;
+       mst_mgr = &aconnector->mst_root->mst_mgr;
  
        if (!crtc_state->connectors_changed && !crtc_state->mode_changed)
                return 0;
                return PTR_ERR(mst_state);
  
        if (!mst_state->pbn_div)
-               mst_state->pbn_div = dm_mst_get_pbn_divider(aconnector->mst_port->dc_link);
+               mst_state->pbn_div = dm_mst_get_pbn_divider(aconnector->mst_root->dc_link);
  
        if (!state->duplicated) {
                int max_bpc = conn_state->max_requested_bpc;
@@@ -6640,7 -6687,7 +6692,7 @@@ static int dm_update_mst_vcpi_slots_for
  
                aconnector = to_amdgpu_dm_connector(connector);
  
-               if (!aconnector->port)
+               if (!aconnector->mst_output_port)
                        continue;
  
                if (!new_con_state || !new_con_state->crtc)
                        dm_conn_state->pbn = pbn;
                        dm_conn_state->vcpi_slots = slot_num;
  
-                       ret = drm_dp_mst_atomic_enable_dsc(state, aconnector->port,
+                       ret = drm_dp_mst_atomic_enable_dsc(state, aconnector->mst_output_port,
                                                           dm_conn_state->pbn, 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->mst_output_port, pbn, true);
                if (vcpi < 0)
                        return vcpi;
  
@@@ -7102,7 -7149,7 +7154,7 @@@ void amdgpu_dm_connector_init_helper(st
                                adev->mode_info.underscan_vborder_property,
                                0);
  
-       if (!aconnector->mst_port)
+       if (!aconnector->mst_root)
                drm_connector_attach_max_bpc_property(&aconnector->base, 8, 16);
  
        /* This defaults to the max in the range, but we want 8bpc for non-edp. */
            connector_type == DRM_MODE_CONNECTOR_eDP) {
                drm_connector_attach_hdr_output_metadata_property(&aconnector->base);
  
-               if (!aconnector->mst_port)
+               if (!aconnector->mst_root)
                        drm_connector_attach_vrr_capable_property(&aconnector->base);
  
  #ifdef CONFIG_DRM_AMD_DC_HDCP
@@@ -7604,6 -7651,7 +7656,7 @@@ static void update_freesync_state_on_st
        new_crtc_state->vrr_infopacket = vrr_infopacket;
  
        new_stream->vrr_infopacket = vrr_infopacket;
+       new_stream->allow_freesync = mod_freesync_get_freesync_enabled(&vrr_params);
  
        if (new_crtc_state->freesync_vrr_info_changed)
                DRM_DEBUG_KMS("VRR packet update: crtc=%u enabled=%d state=%d",
@@@ -8818,22 -8866,15 +8871,15 @@@ static void get_freesync_config_for_crt
        struct drm_display_mode *mode = &new_crtc_state->base.mode;
        int vrefresh = drm_mode_vrefresh(mode);
        bool fs_vid_mode = false;
-       bool drr_active = false;
  
        new_crtc_state->vrr_supported = new_con_state->freesync_capable &&
                                        vrefresh >= aconnector->min_vfreq &&
                                        vrefresh <= aconnector->max_vfreq;
  
-       drr_active = new_crtc_state->vrr_supported &&
-               new_crtc_state->freesync_config.state != VRR_STATE_DISABLED &&
-               new_crtc_state->freesync_config.state != VRR_STATE_INACTIVE &&
-               new_crtc_state->freesync_config.state != VRR_STATE_UNSUPPORTED;
-       if (drr_active)
-               new_crtc_state->stream->ignore_msa_timing_param = true;
        if (new_crtc_state->vrr_supported) {
+               new_crtc_state->stream->ignore_msa_timing_param = true;
                fs_vid_mode = new_crtc_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED;
                config.min_refresh_in_uhz = aconnector->min_vfreq * 1000000;
                config.max_refresh_in_uhz = aconnector->max_vfreq * 1000000;
                config.vsif_supported = true;
@@@ -9032,6 -9073,13 +9078,13 @@@ static int dm_update_crtc_state(struct 
                if (!dm_old_crtc_state->stream)
                        goto skip_modeset;
  
+               /* Unset freesync video if it was active before */
+               if (dm_old_crtc_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED) {
+                       dm_new_crtc_state->freesync_config.state = VRR_STATE_INACTIVE;
+                       dm_new_crtc_state->freesync_config.fixed_refresh_in_uhz = 0;
+               }
+               /* Now check if we should set freesync video mode */
                if (amdgpu_freesync_vid_mode && dm_new_crtc_state->stream &&
                    is_timing_unchanged_for_freesync(new_crtc_state,
                                                     old_crtc_state)) {
@@@ -9593,7 -9641,7 +9646,7 @@@ static int add_affected_mst_dsc_crtcs(s
                        continue;
  
                aconnector = to_amdgpu_dm_connector(connector);
-               if (!aconnector->port || !aconnector->mst_port)
+               if (!aconnector->mst_output_port || !aconnector->mst_root)
                        aconnector = NULL;
                else
                        break;
        if (!aconnector)
                return 0;
  
-       return drm_dp_mst_add_affected_dsc_crtcs(state, &aconnector->mst_port->mst_mgr);
+       return drm_dp_mst_add_affected_dsc_crtcs(state, &aconnector->mst_root->mst_mgr);
  }
  #endif
  
@@@ -9648,6 -9696,8 +9701,8 @@@ static int amdgpu_dm_atomic_check(struc
        bool lock_and_validation_needed = false;
        struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state;
  #if defined(CONFIG_DRM_AMD_DC_DCN)
+       struct drm_dp_mst_topology_mgr *mgr;
+       struct drm_dp_mst_topology_state *mst_state;
        struct dsc_mst_fairness_vars vars[MAX_PIPES];
  #endif
  
                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;
+               drm_connector_list_iter_begin(dev, &iter);
+               drm_for_each_connector_iter(connector, &iter) {
+                       if (connector->index == 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
@@@ -10165,11 -10237,15 +10242,15 @@@ static bool parse_edid_cea(struct amdgp
                struct amdgpu_hdmi_vsdb_info *vsdb_info)
  {
        struct amdgpu_device *adev = drm_to_adev(aconnector->base.dev);
+       bool ret;
  
+       mutex_lock(&adev->dm.dc_lock);
        if (adev->dm.dmub_srv)
-               return parse_edid_cea_dmub(&adev->dm, edid_ext, len, vsdb_info);
+               ret = parse_edid_cea_dmub(&adev->dm, edid_ext, len, vsdb_info);
        else
-               return parse_edid_cea_dmcu(&adev->dm, edid_ext, len, vsdb_info);
+               ret = parse_edid_cea_dmcu(&adev->dm, edid_ext, len, vsdb_info);
+       mutex_unlock(&adev->dm.dc_lock);
+       return ret;
  }
  
  static int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector,
@@@ -10445,6 -10521,7 +10526,7 @@@ int amdgpu_dm_process_dmub_aux_transfer
        ret = p_notify->aux_reply.length;
        *operation_result = p_notify->result;
  out:
+       reinit_completion(&adev->dm.dmub_aux_transfer_done);
        mutex_unlock(&adev->dm.dpia_aux_lock);
        return ret;
  }
@@@ -10472,6 -10549,8 +10554,8 @@@ int amdgpu_dm_process_dmub_set_config_s
                *operation_result = SET_CONFIG_UNKNOWN_ERROR;
        }
  
+       if (!is_cmd_complete)
+               reinit_completion(&adev->dm.dmub_aux_transfer_done);
        mutex_unlock(&adev->dm.dpia_aux_lock);
        return ret;
  }
index 5861b0a6247bc1bb10d5ae4dda45f27f537750d8,4ca37261584a945dcf3cc9575b692b1f8e1d0c32..847c10aa2098ceb279dfae8b61e87281a102d14a
@@@ -3309,13 -3309,8 +3309,13 @@@ int drm_dp_add_payload_part1(struct drm
        int ret;
  
        port = drm_dp_mst_topology_get_port_validated(mgr, payload->port);
 -      if (!port)
 +      if (!port) {
 +              drm_dbg_kms(mgr->dev,
 +                          "VCPI %d for port %p not in topology, not creating a payload\n",
 +                          payload->vcpi, payload->port);
 +              payload->vc_start_slot = -1;
                return 0;
 +      }
  
        if (mgr->payload_count == 0)
                mgr->next_start_slot = mst_state->start_slot;
@@@ -3377,6 -3372,9 +3377,9 @@@ void drm_dp_remove_payload(struct drm_d
  
        mgr->payload_count--;
        mgr->next_start_slot -= payload->time_slots;
+       if (payload->delete)
+               drm_dp_mst_put_port_malloc(payload->port);
  }
  EXPORT_SYMBOL(drm_dp_remove_payload);
  
@@@ -3646,9 -3644,6 +3649,9 @@@ int drm_dp_mst_topology_mgr_set_mst(str
                drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL, 0);
                ret = 0;
                mgr->payload_id_table_cleared = false;
 +
 +              memset(&mgr->down_rep_recv, 0, sizeof(mgr->down_rep_recv));
 +              memset(&mgr->up_req_recv, 0, sizeof(mgr->up_req_recv));
        }
  
  out_unlock:
@@@ -3861,7 -3856,7 +3864,7 @@@ static int drm_dp_mst_handle_down_rep(s
        struct drm_dp_sideband_msg_rx *msg = &mgr->down_rep_recv;
  
        if (!drm_dp_get_one_sb_msg(mgr, false, &mstb))
 -              goto out;
 +              goto out_clear_reply;
  
        /* Multi-packet message transmission, don't clear the reply */
        if (!msg->have_eomt)
@@@ -4335,7 -4330,6 +4338,6 @@@ int drm_dp_atomic_release_time_slots(st
  
        drm_dbg_atomic(mgr->dev, "[MST PORT:%p] TU %d -> 0\n", port, payload->time_slots);
        if (!payload->delete) {
-               drm_dp_mst_put_port_malloc(port);
                payload->pbn = 0;
                payload->delete = true;
                topology_state->payload_mask &= ~BIT(payload->vcpi - 1);
diff --combined include/drm/drm_print.h
index c3753da97c4ece3823d422b3c905dc9b8f08c0e8,094ded23534c76e3990acf1b04d07a4edef17bb9..a93a387f8a1a15b17fe2826e4b09017189394e02
@@@ -521,7 -521,7 +521,7 @@@ __printf(1, 2
  void __drm_err(const char *format, ...);
  
  #if !defined(CONFIG_DRM_USE_DYNAMIC_DEBUG)
- #define __drm_dbg(fmt, ...)           ___drm_dbg(NULL, fmt, ##__VA_ARGS__)
+ #define __drm_dbg(cat, fmt, ...)              ___drm_dbg(NULL, cat, fmt, ##__VA_ARGS__)
  #else
  #define __drm_dbg(cat, fmt, ...)                                      \
        _dynamic_func_call_cls(cat, fmt, ___drm_dbg,                    \
  #define drm_dbg_kms_ratelimited(drm, fmt, ...) \
        __DRM_DEFINE_DBG_RATELIMITED(KMS, drm, fmt, ## __VA_ARGS__)
  
 -/* NOTE: this is deprecated in favor of drm_dbg_kms_ratelimited(NULL, ...). */
 -#define DRM_DEBUG_KMS_RATELIMITED(fmt, ...) drm_dbg_kms_ratelimited(NULL, fmt, ## __VA_ARGS__)
 -
  /*
   * struct drm_device based WARNs
   *
This page took 0.14455 seconds and 4 git commands to generate.