Merge tag 'amd-drm-next-6.19-2025-10-29' of https://gitlab.freedesktop.org/agd5f/linux into drm-next

amd-drm-next-6.19-2025-10-29:

amdgpu:
- VPE idle handler fix
- Re-enable DM idle optimizations
- DCN3.0 fix
- SMU fix
- Powerplay fixes for fiji/iceland
- License copy-pasta fixes
- HDP eDP panel fix
- Vblank fix
- RAS fixes
- SR-IOV updates
- SMU 13 VCN reset fix
- DMUB fixes
- DC frame limit fix
- Additional DC underflow logging
- DCN 3.1.5 fixes
- DC Analog encoders support
- Enable DC on bonaire by default
- UserQ fixes
- Remove redundant pm_runtime_mark_last_busy() calls

amdkfd:
- Process cleanup fix
- Misc fixes

radeon:
- devm migration fixes
- Remove redundant pm_runtime_mark_last_busy() calls

UAPI
- Add ABM KMS property
  Proposed kwin changes: https://invent.kde.org/plasma/kwin/-/merge_requests/6028

Signed-off-by: Simona Vetter <simona.vetter@ffwll.ch>
From: Alex Deucher <alexander.deucher@amd.com>
Link: https://patch.msgid.link/20251029205713.9480-1-alexander.deucher@amd.com
This commit is contained in:
Simona Vetter
2025-10-31 22:08:23 +01:00
256 changed files with 3546 additions and 889 deletions

View File

@@ -3853,7 +3853,9 @@ void amdgpu_dm_update_connector_after_detect(
drm_dbg_kms(dev, "DCHPD: connector_id=%d: Old sink=%p New sink=%p\n",
aconnector->connector_id, aconnector->dc_sink, sink);
guard(mutex)(&dev->mode_config.mutex);
/* When polling, DRM has already locked the mutex for us. */
if (!drm_kms_helper_is_poll_worker())
mutex_lock(&dev->mode_config.mutex);
/*
* 1. Update status of the drm connector
@@ -3916,6 +3918,10 @@ void amdgpu_dm_update_connector_after_detect(
}
update_subconnector_property(aconnector);
/* When polling, the mutex will be unlocked for us by DRM. */
if (!drm_kms_helper_is_poll_worker())
mutex_unlock(&dev->mode_config.mutex);
}
static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector)
@@ -5200,6 +5206,7 @@ static int initialize_plane(struct amdgpu_display_manager *dm,
static void setup_backlight_device(struct amdgpu_display_manager *dm,
struct amdgpu_dm_connector *aconnector)
{
struct amdgpu_dm_backlight_caps *caps;
struct dc_link *link = aconnector->dc_link;
int bl_idx = dm->num_of_edps;
@@ -5219,6 +5226,13 @@ static void setup_backlight_device(struct amdgpu_display_manager *dm,
dm->num_of_edps++;
update_connector_ext_caps(aconnector);
caps = &dm->backlight_caps[aconnector->bl_idx];
/* Only offer ABM property when non-OLED and user didn't turn off by module parameter */
if (!caps->ext_caps->bits.oled && amdgpu_dm_abm_level < 0)
drm_object_attach_property(&aconnector->base.base,
dm->adev->mode_info.abm_level_property,
ABM_SYSFS_CONTROL);
}
static void amdgpu_set_panel_orientation(struct drm_connector *connector);
@@ -7218,29 +7232,101 @@ finish:
return stream;
}
/**
* amdgpu_dm_connector_poll() - Poll a connector to see if it's connected to a display
*
* Used for connectors that don't support HPD (hotplug detection)
* to periodically checked whether the connector is connected to a display.
*/
static enum drm_connector_status
amdgpu_dm_connector_poll(struct amdgpu_dm_connector *aconnector, bool force)
{
struct drm_connector *connector = &aconnector->base;
struct drm_device *dev = connector->dev;
struct amdgpu_device *adev = drm_to_adev(dev);
struct dc_link *link = aconnector->dc_link;
enum dc_connection_type conn_type = dc_connection_none;
enum drm_connector_status status = connector_status_disconnected;
/* When we determined the connection using DAC load detection,
* do NOT poll the connector do detect disconnect because
* that would run DAC load detection again which can cause
* visible visual glitches.
*
* Only allow to poll such a connector again when forcing.
*/
if (!force && link->local_sink && link->type == dc_connection_dac_load)
return connector->status;
mutex_lock(&aconnector->hpd_lock);
if (dc_link_detect_connection_type(aconnector->dc_link, &conn_type) &&
conn_type != dc_connection_none) {
mutex_lock(&adev->dm.dc_lock);
/* Only call full link detection when a sink isn't created yet,
* ie. just when the display is plugged in, otherwise we risk flickering.
*/
if (link->local_sink ||
dc_link_detect(link, DETECT_REASON_HPD))
status = connector_status_connected;
mutex_unlock(&adev->dm.dc_lock);
}
if (connector->status != status) {
if (status == connector_status_disconnected) {
if (link->local_sink)
dc_sink_release(link->local_sink);
link->local_sink = NULL;
link->dpcd_sink_count = 0;
link->type = dc_connection_none;
}
amdgpu_dm_update_connector_after_detect(aconnector);
}
mutex_unlock(&aconnector->hpd_lock);
return status;
}
/**
* amdgpu_dm_connector_detect() - Detect whether a DRM connector is connected to a display
*
* A connector is considered connected when it has a sink that is not NULL.
* For connectors that support HPD (hotplug detection), the connection is
* handled in the HPD interrupt.
* For connectors that may not support HPD, such as analog connectors,
* DRM will call this function repeatedly to poll them.
*
* Notes:
* 1. This interface is NOT called in context of HPD irq.
* 2. This interface *is called* in context of user-mode ioctl. Which
* makes it a bad place for *any* MST-related activity.
*/
static enum drm_connector_status
amdgpu_dm_connector_detect(struct drm_connector *connector, bool force)
{
bool connected;
struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
/*
* Notes:
* 1. This interface is NOT called in context of HPD irq.
* 2. This interface *is called* in context of user-mode ioctl. Which
* makes it a bad place for *any* MST-related activity.
*/
if (aconnector->base.force == DRM_FORCE_UNSPECIFIED &&
!aconnector->fake_enable)
connected = (aconnector->dc_sink != NULL);
else
connected = (aconnector->base.force == DRM_FORCE_ON ||
aconnector->base.force == DRM_FORCE_ON_DIGITAL);
update_subconnector_property(aconnector);
return (connected ? connector_status_connected :
if (aconnector->base.force == DRM_FORCE_ON ||
aconnector->base.force == DRM_FORCE_ON_DIGITAL)
return connector_status_connected;
else if (aconnector->base.force == DRM_FORCE_OFF)
return connector_status_disconnected;
/* Poll analog connectors and only when either
* disconnected or connected to an analog display.
*/
if (drm_kms_helper_is_poll_worker() &&
dc_connector_supports_analog(aconnector->dc_link->link_id.id) &&
(!aconnector->dc_sink || aconnector->dc_sink->edid_caps.analog))
return amdgpu_dm_connector_poll(aconnector, force);
return (aconnector->dc_sink ? connector_status_connected :
connector_status_disconnected);
}
@@ -7291,6 +7377,20 @@ int amdgpu_dm_connector_atomic_set_property(struct drm_connector *connector,
} else if (property == adev->mode_info.underscan_property) {
dm_new_state->underscan_enable = val;
ret = 0;
} else if (property == adev->mode_info.abm_level_property) {
switch (val) {
case ABM_SYSFS_CONTROL:
dm_new_state->abm_sysfs_forbidden = false;
break;
case ABM_LEVEL_OFF:
dm_new_state->abm_sysfs_forbidden = true;
dm_new_state->abm_level = ABM_LEVEL_IMMEDIATE_DISABLE;
break;
default:
dm_new_state->abm_sysfs_forbidden = true;
dm_new_state->abm_level = val;
};
ret = 0;
}
return ret;
@@ -7333,6 +7433,13 @@ int amdgpu_dm_connector_atomic_get_property(struct drm_connector *connector,
} else if (property == adev->mode_info.underscan_property) {
*val = dm_state->underscan_enable;
ret = 0;
} else if (property == adev->mode_info.abm_level_property) {
if (!dm_state->abm_sysfs_forbidden)
*val = ABM_SYSFS_CONTROL;
else
*val = (dm_state->abm_level != ABM_LEVEL_IMMEDIATE_DISABLE) ?
dm_state->abm_level : 0;
ret = 0;
}
return ret;
@@ -7385,10 +7492,16 @@ static ssize_t panel_power_savings_store(struct device *device,
return -EINVAL;
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
to_dm_connector_state(connector->state)->abm_level = val ?:
ABM_LEVEL_IMMEDIATE_DISABLE;
if (to_dm_connector_state(connector->state)->abm_sysfs_forbidden)
ret = -EBUSY;
else
to_dm_connector_state(connector->state)->abm_level = val ?:
ABM_LEVEL_IMMEDIATE_DISABLE;
drm_modeset_unlock(&dev->mode_config.connection_mutex);
if (ret)
return ret;
drm_kms_helper_hotplug_event(dev);
return count;
@@ -8228,7 +8341,7 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
return 0;
}
static int to_drm_connector_type(enum signal_type st)
static int to_drm_connector_type(enum signal_type st, uint32_t connector_id)
{
switch (st) {
case SIGNAL_TYPE_HDMI_TYPE_A:
@@ -8244,6 +8357,10 @@ static int to_drm_connector_type(enum signal_type st)
return DRM_MODE_CONNECTOR_DisplayPort;
case SIGNAL_TYPE_DVI_DUAL_LINK:
case SIGNAL_TYPE_DVI_SINGLE_LINK:
if (connector_id == CONNECTOR_ID_SINGLE_LINK_DVII ||
connector_id == CONNECTOR_ID_DUAL_LINK_DVII)
return DRM_MODE_CONNECTOR_DVII;
return DRM_MODE_CONNECTOR_DVID;
case SIGNAL_TYPE_VIRTUAL:
return DRM_MODE_CONNECTOR_VIRTUAL;
@@ -8295,7 +8412,7 @@ static void amdgpu_dm_get_native_mode(struct drm_connector *connector)
static struct drm_display_mode *
amdgpu_dm_create_common_mode(struct drm_encoder *encoder,
char *name,
const char *name,
int hdisplay, int vdisplay)
{
struct drm_device *dev = encoder->dev;
@@ -8317,6 +8434,24 @@ amdgpu_dm_create_common_mode(struct drm_encoder *encoder,
}
static const struct amdgpu_dm_mode_size {
char name[DRM_DISPLAY_MODE_LEN];
int w;
int h;
} common_modes[] = {
{ "640x480", 640, 480},
{ "800x600", 800, 600},
{ "1024x768", 1024, 768},
{ "1280x720", 1280, 720},
{ "1280x800", 1280, 800},
{"1280x1024", 1280, 1024},
{ "1440x900", 1440, 900},
{"1680x1050", 1680, 1050},
{"1600x1200", 1600, 1200},
{"1920x1080", 1920, 1080},
{"1920x1200", 1920, 1200}
};
static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder,
struct drm_connector *connector)
{
@@ -8327,23 +8462,6 @@ static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder,
to_amdgpu_dm_connector(connector);
int i;
int n;
struct mode_size {
char name[DRM_DISPLAY_MODE_LEN];
int w;
int h;
} common_modes[] = {
{ "640x480", 640, 480},
{ "800x600", 800, 600},
{ "1024x768", 1024, 768},
{ "1280x720", 1280, 720},
{ "1280x800", 1280, 800},
{"1280x1024", 1280, 1024},
{ "1440x900", 1440, 900},
{"1680x1050", 1680, 1050},
{"1600x1200", 1600, 1200},
{"1920x1080", 1920, 1080},
{"1920x1200", 1920, 1200}
};
if ((connector->connector_type != DRM_MODE_CONNECTOR_eDP) &&
(connector->connector_type != DRM_MODE_CONNECTOR_LVDS))
@@ -8544,6 +8662,10 @@ static void amdgpu_dm_connector_add_freesync_modes(struct drm_connector *connect
if (!(amdgpu_freesync_vid_mode && drm_edid))
return;
if (!amdgpu_dm_connector->dc_sink || amdgpu_dm_connector->dc_sink->edid_caps.analog ||
!dc_supports_vrr(amdgpu_dm_connector->dc_sink->ctx->dce_version))
return;
if (amdgpu_dm_connector->max_vfreq - amdgpu_dm_connector->min_vfreq > 10)
amdgpu_dm_connector->num_modes +=
add_fs_modes(amdgpu_dm_connector);
@@ -8567,6 +8689,15 @@ static int amdgpu_dm_connector_get_modes(struct drm_connector *connector)
if (dc->link_srv->dp_get_encoding_format(verified_link_cap) == DP_128b_132b_ENCODING)
amdgpu_dm_connector->num_modes +=
drm_add_modes_noedid(connector, 1920, 1080);
if (amdgpu_dm_connector->dc_sink->edid_caps.analog) {
/* Analog monitor connected by DAC load detection.
* Add common modes. It will be up to the user to select one that works.
*/
for (int i = 0; i < ARRAY_SIZE(common_modes); i++)
amdgpu_dm_connector->num_modes += drm_add_modes_noedid(
connector, common_modes[i].w, common_modes[i].h);
}
} else {
amdgpu_dm_connector_ddc_get_modes(connector, drm_edid);
if (encoder)
@@ -8635,6 +8766,11 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
case DRM_MODE_CONNECTOR_DVID:
aconnector->base.polled = DRM_CONNECTOR_POLL_HPD;
break;
case DRM_MODE_CONNECTOR_DVII:
case DRM_MODE_CONNECTOR_VGA:
aconnector->base.polled =
DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
break;
default:
break;
}
@@ -8836,7 +8972,7 @@ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm,
goto out_free;
}
connector_type = to_drm_connector_type(link->connector_signal);
connector_type = to_drm_connector_type(link->connector_signal, link->link_id.id);
res = drm_connector_init_with_ddc(
dm->ddev,