- Freesync fix
 - GPUVM fix
 - Debugfs fixes
 - HDMI fixes
 - IPS fix
 - GPU reset fix
 - RGB quantization fixes
 - SMU 13.0.x fixes
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQQgO5Idg2tXNTSZAr293/aFa7yZ2AUCaqMRBAAKCRC93/aFa7yZ
 2H1gAQDtthjy2TqGB7aoqB9YpPH95RpHARK7puEM2Ehi1FxElQD/cQV/Wemy98an
 pVzynHB7QuTTdkbdmp2FTqj78t0S8Qo=
 =KLq3
 -----END PGP SIGNATURE-----

Merge tag 'amd-drm-fixes-7.3-2026-09-10' of https://gitlab.freedesktop.org/drm/amdgpu/kernel into drm-fixes

amdgpu:
- Freesync fix
- GPUVM fix
- Debugfs fixes
- HDMI fixes
- IPS fix
- GPU reset fix
- RGB quantization fixes
- SMU 13.0.x fixes

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Alex Deucher <alexander.deucher@amd.com>
Link: https://patch.msgid.link/20260910202516.825788-1-alexander.deucher@amd.com
This commit is contained in:
Dave Airlie 2026-09-11 17:59:56 +10:00
commit b1edd3a3e0
12 changed files with 99 additions and 44 deletions

View File

@ -1701,9 +1701,8 @@ u64 amdgpu_bo_print_info(int id, struct amdgpu_bo *bo, struct seq_file *m)
if (dma_resv_trylock(bo->tbo.base.resv)) {
dma_resv_describe(bo->tbo.base.resv, m);
dma_resv_unlock(bo->tbo.base.resv);
} else {
seq_puts(m, "\n");
}
seq_puts(m, "\n");
return size;
}

View File

@ -191,6 +191,8 @@ amdgpu_ttm_job_submit(struct amdgpu_device *adev, struct amdgpu_ttm_buffer_entit
* @tmz: if we should setup a TMZ enabled mapping
* @size: in number of bytes to map, out number of bytes mapped
* @addr: resulting address inside the MC address space
* @vm_needs_flush: out, set true if a GART window was programmed (VMID 0 flush
* needed) or false for a direct address
*
* Setup one of the GART windows to access a specific piece of memory or return
* the physical address for local memory.
@ -200,7 +202,8 @@ static int amdgpu_ttm_map_buffer(struct amdgpu_ttm_buffer_entity *entity,
struct ttm_resource *mem,
struct amdgpu_res_cursor *mm_cur,
unsigned int window,
bool tmz, uint64_t *size, uint64_t *addr)
bool tmz, uint64_t *size, uint64_t *addr,
bool *vm_needs_flush)
{
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev);
unsigned int offset, num_pages, num_dw, num_bytes;
@ -221,9 +224,12 @@ static int amdgpu_ttm_map_buffer(struct amdgpu_ttm_buffer_entity *entity,
if (!tmz && mem->start != AMDGPU_BO_INVALID_OFFSET) {
*addr = amdgpu_ttm_domain_start(adev, mem->mem_type) +
mm_cur->start;
*vm_needs_flush = false;
return 0;
}
/* A GART window is programmed below, so its VMID 0 TLB needs a flush */
*vm_needs_flush = true;
/*
* If start begins at an offset inside the page, then adjust the size
@ -324,6 +330,7 @@ static int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev,
while (src_mm.remaining) {
uint64_t from, to, cur_size, tiling_flags;
uint32_t num_type, data_format, max_com, write_compress_disable;
bool src_vm_flush, dst_vm_flush;
struct dma_fence *next;
/* Never copy more than 256MiB at once to avoid a timeout */
@ -331,12 +338,12 @@ static int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev,
/* Map src to window 0 and dst to window 1. */
r = amdgpu_ttm_map_buffer(entity, src->bo, src->mem, &src_mm,
0, tmz, &cur_size, &from);
0, tmz, &cur_size, &from, &src_vm_flush);
if (r)
goto error;
r = amdgpu_ttm_map_buffer(entity, dst->bo, dst->mem, &dst_mm,
1, tmz, &cur_size, &to);
1, tmz, &cur_size, &to, &dst_vm_flush);
if (r)
goto error;
@ -364,7 +371,7 @@ static int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev,
}
r = amdgpu_copy_buffer(adev, entity, from, to, cur_size, resv,
&next, true, copy_flags);
&next, src_vm_flush || dst_vm_flush, copy_flags);
if (r)
goto error;
@ -2624,6 +2631,7 @@ int amdgpu_ttm_clear_buffer(struct amdgpu_ttm_buffer_entity *entity,
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
struct dma_fence *fence = NULL;
struct amdgpu_res_cursor dst;
bool vm_needs_flush = false;
int r;
if (!entity)
@ -2645,13 +2653,13 @@ int amdgpu_ttm_clear_buffer(struct amdgpu_ttm_buffer_entity *entity,
cur_size = min(dst.size, 256ULL << 20);
r = amdgpu_ttm_map_buffer(entity, &bo->tbo, bo->tbo.resource, &dst,
0, false, &cur_size, &to);
0, false, &cur_size, &to, &vm_needs_flush);
if (r)
goto error;
r = amdgpu_ttm_fill_mem(adev, entity,
0, to, cur_size, resv,
&next, true, k_job_id);
&next, vm_needs_flush, k_job_id);
if (r)
goto error;

View File

@ -747,9 +747,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
}
if (adev->dm.dc->caps.max_links > 0) {
adev->dm.hdmi_frl_status_polling_wq =
create_singlethread_workqueue("hdmi_frl_status_polling_workqueue");
create_singlethread_workqueue("hdmi_frl_status_polling_wq");
if (!adev->dm.hdmi_frl_status_polling_wq)
drm_err(adev_to_drm(adev), "failed to initialize hdmi_frl_status_polling_workqueue\n");
drm_err(adev_to_drm(adev), "failed to initialize hdmi_frl_status_polling_wq\n");
}
if (dc_is_dmub_outbox_supported(adev->dm.dc)) {
init_completion(&adev->dm.dmub_aux_transfer_done);
@ -1972,6 +1972,10 @@ static int dm_resume(struct amdgpu_ip_block *ip_block)
/* On resume we need to rewrite the MSTM control bits to enable MST*/
s3_handle_mst(ddev, false);
/* Exit IPS before the detection loop's first AUX/DDC access. */
scoped_guard(mutex, &dm->dc_lock)
dc_exit_ips_for_hw_access(dm->dc);
/* Do detection*/
drm_connector_list_iter_begin(ddev, &iter);
drm_for_each_connector_iter(connector, &iter) {

View File

@ -756,10 +756,14 @@ amdgpu_dm_get_output_color_space(const struct dc_crtc_timing *dc_crtc_timing,
break;
case DRM_MODE_COLORIMETRY_BT2020_RGB:
case DRM_MODE_COLORIMETRY_BT2020_YCC:
if (dc_crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB)
color_space = COLOR_SPACE_2020_RGB_FULLRANGE;
else
if (dc_crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB) {
if (connector_state->hdmi.broadcast_rgb == DRM_HDMI_BROADCAST_RGB_LIMITED)
color_space = COLOR_SPACE_2020_RGB_LIMITEDRANGE;
else
color_space = COLOR_SPACE_2020_RGB_FULLRANGE;
} else {
color_space = COLOR_SPACE_2020_YCBCR_LIMITED;
}
break;
case DRM_MODE_COLORIMETRY_DEFAULT: /* ITU601 */
default:
@ -3937,17 +3941,15 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
}
/* Handle MCCS */
if (do_mccs)
if (do_mccs) {
dm_helpers_read_mccs_caps(adev->dm.dc->ctx, amdgpu_dm_connector->dc_link, sink);
if ((sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A ||
as_type == FREESYNC_TYPE_PCON_IN_WHITELIST) &&
(!sink->edid_caps.freesync_vcp_code ||
(sink->edid_caps.freesync_vcp_code && !sink->mccs_caps.freesync_supported)))
freesync_capable = false;
if (sink->edid_caps.freesync_vcp_code && !sink->mccs_caps.freesync_supported)
freesync_capable = false;
if (do_mccs && sink->mccs_caps.freesync_supported && freesync_capable)
dm_helpers_mccs_vcp_set(adev->dm.dc->ctx, amdgpu_dm_connector->dc_link, sink);
if (sink->mccs_caps.freesync_supported && freesync_capable)
dm_helpers_mccs_vcp_set(adev->dm.dc->ctx, amdgpu_dm_connector->dc_link, sink);
}
update:
if (dm_con_state)

View File

@ -196,7 +196,6 @@ static ssize_t dp_link_settings_read(struct file *f, char __user *buf,
char *rd_buf_ptr = NULL;
const uint32_t rd_buf_size = 100;
uint32_t result = 0;
uint8_t str_len = 0;
int r;
if (*pos & 3 || size & 3)
@ -208,29 +207,26 @@ static ssize_t dp_link_settings_read(struct file *f, char __user *buf,
rd_buf_ptr = rd_buf;
str_len = strlen("Current: %d 0x%x %d ");
snprintf(rd_buf_ptr, str_len, "Current: %d 0x%x %d ",
rd_buf_ptr += scnprintf(rd_buf_ptr, rd_buf_size - (rd_buf_ptr - rd_buf),
"Current: %d 0x%x %d ",
link->cur_link_settings.lane_count,
link->cur_link_settings.link_rate,
link->cur_link_settings.link_spread);
rd_buf_ptr += str_len;
str_len = strlen("Verified: %d 0x%x %d ");
snprintf(rd_buf_ptr, str_len, "Verified: %d 0x%x %d ",
rd_buf_ptr += scnprintf(rd_buf_ptr, rd_buf_size - (rd_buf_ptr - rd_buf),
"Verified: %d 0x%x %d ",
link->verified_link_cap.lane_count,
link->verified_link_cap.link_rate,
link->verified_link_cap.link_spread);
rd_buf_ptr += str_len;
str_len = strlen("Reported: %d 0x%x %d ");
snprintf(rd_buf_ptr, str_len, "Reported: %d 0x%x %d ",
rd_buf_ptr += scnprintf(rd_buf_ptr, rd_buf_size - (rd_buf_ptr - rd_buf),
"Reported: %d 0x%x %d ",
link->reported_link_cap.lane_count,
link->reported_link_cap.link_rate,
link->reported_link_cap.link_spread);
rd_buf_ptr += str_len;
str_len = strlen("Preferred: %d 0x%x %d ");
snprintf(rd_buf_ptr, str_len, "Preferred: %d 0x%x %d\n",
rd_buf_ptr += scnprintf(rd_buf_ptr, rd_buf_size - (rd_buf_ptr - rd_buf),
"Preferred: %d 0x%x %d\n",
link->preferred_link_setting.lane_count,
link->preferred_link_setting.link_rate,
link->preferred_link_setting.link_spread);

View File

@ -200,6 +200,7 @@ enum dc_edid_status dm_helpers_parse_edid_caps(
edid_caps->edid_hdmi = connector->display_info.is_hdmi;
if (edid_caps->edid_hdmi) {
edid_caps->qs_bit = connector->display_info.rgb_quant_range_selectable;
populate_hdmi_info_from_connector(link->dc->config.enable_frl, &connector->display_info.hdmi, edid_caps);
drm_dbg_driver(connector->dev, "%s: HDMI_FRL [%s] max_frl_rate %d\n", __func__, connector->name, edid_caps->max_frl_rate);
if (edid_caps->frl_dsc_support)
@ -1202,9 +1203,10 @@ void populate_hdmi_info_from_connector(bool enable_frl, struct drm_hdmi_info *hd
edid_caps->max_frl_rate = get_max_frl_rate(hdmi->max_lanes, hdmi->max_frl_rate_per_lane);
edid_caps->frl_dsc_support = hdmi->dsc_cap.v_1p2;
if (edid_caps->frl_dsc_support) {
if (hdmi->dsc_cap.bpc_supported == 10)
/* HF-VSDB DSC max bpc is cumulative: >=12 implies 10 and 8. */
if (hdmi->dsc_cap.bpc_supported >= 10)
edid_caps->frl_dsc_10bpc = true;
else if (hdmi->dsc_cap.bpc_supported == 12)
if (hdmi->dsc_cap.bpc_supported >= 12)
edid_caps->frl_dsc_12bpc = true;
edid_caps->frl_dsc_all_bpp = hdmi->dsc_cap.all_bpp;
edid_caps->frl_dsc_native_420 = hdmi->dsc_cap.native_420;

View File

@ -567,6 +567,23 @@ static void dm_test_output_color_space_bt2020_rgb(struct kunit *test)
(int)COLOR_SPACE_2020_RGB_FULLRANGE);
}
/**
* dm_test_output_color_space_bt2020_rgb_limited - Test limited BT.2020 RGB
* @test: The KUnit test context
*/
static void dm_test_output_color_space_bt2020_rgb_limited(struct kunit *test)
{
struct dc_crtc_timing timing = {};
struct drm_connector_state state = {};
timing.pixel_encoding = PIXEL_ENCODING_RGB;
state.colorspace = DRM_MODE_COLORIMETRY_BT2020_RGB;
state.hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_LIMITED;
KUNIT_EXPECT_EQ(test, (int)amdgpu_dm_get_output_color_space(&timing, &state),
(int)COLOR_SPACE_2020_RGB_LIMITEDRANGE);
}
/**
* dm_test_output_color_space_bt2020_ycc - Test Output color space bt2020 ycc
* @test: The KUnit test context
@ -638,6 +655,24 @@ static void dm_test_output_color_space_bt2020_ycc_rgb_encoding(struct kunit *tes
(int)COLOR_SPACE_2020_RGB_FULLRANGE);
}
/**
* dm_test_output_color_space_bt2020_ycc_rgb_encoding_limited - Test limited
* BT.2020 RGB output selected through the BT.2020 YCC connector colorspace
* @test: The KUnit test context
*/
static void dm_test_output_color_space_bt2020_ycc_rgb_encoding_limited(struct kunit *test)
{
struct dc_crtc_timing timing = {};
struct drm_connector_state state = {};
timing.pixel_encoding = PIXEL_ENCODING_RGB;
state.colorspace = DRM_MODE_COLORIMETRY_BT2020_YCC;
state.hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_LIMITED;
KUNIT_EXPECT_EQ(test, (int)amdgpu_dm_get_output_color_space(&timing, &state),
(int)COLOR_SPACE_2020_RGB_LIMITEDRANGE);
}
/**
* dm_test_output_color_space_bt2020_rgb_ycc_encoding - Test Output color space
* bt2020 rgb with non-rgb pixel encoding falls back to limited ycbcr
@ -5422,10 +5457,12 @@ static struct kunit_case amdgpu_dm_connector_tests[] = {
KUNIT_CASE(dm_test_output_color_space_bt709_y_only),
KUNIT_CASE(dm_test_output_color_space_oprgb),
KUNIT_CASE(dm_test_output_color_space_bt2020_rgb),
KUNIT_CASE(dm_test_output_color_space_bt2020_rgb_limited),
KUNIT_CASE(dm_test_output_color_space_bt2020_ycc),
KUNIT_CASE(dm_test_output_color_space_default_ycbcr709_y_only),
KUNIT_CASE(dm_test_output_color_space_default_ycbcr601),
KUNIT_CASE(dm_test_output_color_space_bt2020_ycc_rgb_encoding),
KUNIT_CASE(dm_test_output_color_space_bt2020_ycc_rgb_encoding_limited),
KUNIT_CASE(dm_test_output_color_space_bt2020_rgb_ycc_encoding),
/* Tests for amdgpu_dm_convert_dc_color_depth_into_bpc */
KUNIT_CASE(dm_test_convert_color_depth_bpc_mappings),

View File

@ -358,12 +358,14 @@ static void dm_test_parse_edid_caps_hdmi_frl(struct kunit *test)
/* Drive the HDMI/FRL branch */
connector->display_info.is_hdmi = true;
connector->display_info.rgb_quant_range_selectable = true;
connector->display_info.hdmi.scdc.supported = true;
connector->display_info.hdmi.max_lanes = 4;
connector->display_info.hdmi.max_frl_rate_per_lane = 12;
KUNIT_EXPECT_EQ(test, dm_helpers_parse_edid_caps(link, dc_edid, edid_caps), EDID_OK);
KUNIT_EXPECT_TRUE(test, edid_caps->edid_hdmi);
KUNIT_EXPECT_EQ(test, edid_caps->qs_bit, 1);
KUNIT_EXPECT_TRUE(test, edid_caps->scdc_present);
/* max_lanes 4 + max_frl_rate_per_lane 12 -> rate index 6 */
KUNIT_EXPECT_EQ(test, edid_caps->max_frl_rate, 6);
@ -909,7 +911,7 @@ static void dm_test_populate_hdmi_frl_dsc_12bpc(struct kunit *test)
KUNIT_EXPECT_EQ(test, caps->max_frl_rate, 2);
KUNIT_EXPECT_TRUE(test, caps->frl_dsc_support);
KUNIT_EXPECT_FALSE(test, caps->frl_dsc_10bpc);
KUNIT_EXPECT_TRUE(test, caps->frl_dsc_10bpc);
KUNIT_EXPECT_TRUE(test, caps->frl_dsc_12bpc);
KUNIT_EXPECT_EQ(test, caps->frl_dsc_max_slices, 7);
KUNIT_EXPECT_EQ(test, caps->frl_dsc_max_frl_rate, 1);

View File

@ -3198,6 +3198,7 @@ static struct dc_update_descriptor check_update_surfaces_for_stream(
}
if ((stream_update->hdr_static_metadata && !stream_update->stream->use_dynamic_meta) ||
stream_update->output_color_space ||
stream_update->vrr_infopacket ||
stream_update->vsc_infopacket ||
stream_update->vsp_infopacket ||
@ -4188,6 +4189,7 @@ static void commit_planes_do_stream_update_sequence(struct dc *dc,
hwss_add_setup_periodic_interrupt(&seq_state, dc, pipe_ctx);
if ((stream_update->hdr_static_metadata && !stream->use_dynamic_meta) ||
stream_update->output_color_space ||
stream_update->vrr_infopacket ||
stream_update->vsc_infopacket ||
stream_update->vsp_infopacket ||
@ -4370,6 +4372,7 @@ static void commit_planes_do_stream_update(struct dc *dc,
dc->hwss.setup_periodic_interrupt(dc, pipe_ctx);
if ((stream_update->hdr_static_metadata && !stream->use_dynamic_meta) ||
stream_update->output_color_space ||
stream_update->vrr_infopacket ||
stream_update->vsc_infopacket ||
stream_update->vsp_infopacket ||

View File

@ -348,7 +348,8 @@ int amdgpu_dpm_switch_power_profile(struct amdgpu_device *adev,
const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
int ret = 0;
if (amdgpu_sriov_vf(adev))
if (amdgpu_sriov_vf(adev) ||
amdgpu_in_reset(adev))
return 0;
if (pp_funcs && pp_funcs->switch_power_profile) {
@ -367,7 +368,8 @@ int amdgpu_dpm_pause_power_profile(struct amdgpu_device *adev,
const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
int ret = 0;
if (amdgpu_sriov_vf(adev))
if (amdgpu_sriov_vf(adev) ||
amdgpu_in_reset(adev))
return 0;
if (pp_funcs && pp_funcs->pause_power_profile) {

View File

@ -2092,11 +2092,11 @@ static ssize_t smu_v13_0_0_get_gpu_metrics(struct smu_context *smu,
gpu_metrics->average_socket_power = metrics->AverageSocketPower;
if ((mp1_ver == IP_VERSION(13, 0, 0) && smu->smc_fw_version <= 0x004e1e00) ||
(mp1_ver == IP_VERSION(13, 0, 10) && smu->smc_fw_version <= 0x00500800))
if ((mp1_ver == IP_VERSION(13, 0, 0) &&
(smu->smc_fw_version <= 0x004e1e00 || smu->smc_fw_version >= 0x004e8600)) ||
(mp1_ver == IP_VERSION(13, 0, 10) &&
smu->smc_fw_version <= 0x00500800))
gpu_metrics->energy_accumulator = metrics->EnergyAccumulator;
else
gpu_metrics->energy_accumulator = UINT_MAX;
if (metrics->AverageGfxActivity <= SMU_13_0_0_BUSY_THRESHOLD)
gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPostDs;

View File

@ -2097,8 +2097,8 @@ static ssize_t smu_v13_0_7_get_gpu_metrics(struct smu_context *smu,
metrics->Vcn1ActivityPercentage);
gpu_metrics->average_socket_power = metrics->AverageSocketPower;
gpu_metrics->energy_accumulator = smu->smc_fw_version <= 0x00521400 ?
metrics->EnergyAccumulator : UINT_MAX;
if (smu->smc_fw_version <= 0x00521400)
gpu_metrics->energy_accumulator = metrics->EnergyAccumulator;
if (metrics->AverageGfxActivity <= SMU_13_0_7_BUSY_THRESHOLD)
gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPostDs;