* [PATCH] drm/amd/amdgpu: Add 5K Support for iMac20,1 and iMac20,2
@ 2026-11-04 19:36 Atharva Tiwari
2026-11-04 19:52 ` Alex Deucher
0 siblings, 1 reply; 4+ messages in thread
From: Atharva Tiwari @ 2026-11-04 19:36 UTC (permalink / raw)
Cc: Atharva Tiwari, Alex Deucher, Christian König, David Airlie,
Simona Vetter, Harry Wentland, Leo Li, Rodrigo Siqueira, amd-gfx,
dri-devel, linux-kernel
This code adds support for 5K in iMac20,1 and iMac20,2 with
support of changing resolutions.
Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4455
Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4895
Signed-off-by: Atharva Tiwari <atharvatiwarilinuxdev@gmail.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 32 ++++++++++++++--
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 26 +++++++++++++
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 7 ++++
.../display/amdgpu_dm/amdgpu_dm_connector.c | 19 +++++++++-
.../amd/display/amdgpu_dm/amdgpu_dm_quirks.c | 29 ++++++++++++++-
.../gpu/drm/amd/display/dc/core/dc_resource.c | 8 ++++
drivers/gpu/drm/amd/display/dc/dc.h | 2 +
.../amd/display/dc/hwss/dce110/dce110_hwseq.c | 37 +++++++++++++++++--
.../drm/amd/display/dc/link/link_detection.c | 14 ++++++-
.../gpu/drm/amd/display/dc/link/link_dpms.c | 3 ++
.../display/dc/link/protocols/link_dp_phy.c | 5 +++
.../dc/link/protocols/link_dp_training.c | 9 ++++-
12 files changed, 180 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
index 890792a94..fc107e4fa 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
@@ -21,6 +21,7 @@
*
*/
+#include <linux/dmi.h>
#include <linux/firmware.h>
#include <linux/kernfs.h>
@@ -3412,6 +3413,22 @@ static int amdgpu_discovery_set_ualink_ip_blocks(struct amdgpu_device *adev)
return 0;
}
+static const struct dmi_system_id imac5k_table[] = {
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "iMac20,1"),
+ },
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "iMac20,2"),
+ },
+ },
+ {}
+};
+
int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
{
int r;
@@ -4026,15 +4043,24 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
}
}
+ /* TODO: We should enable 5K in EFI and remove this quirk */
+ if (unlikely(dmi_check_system(imac5k_table))) {
+ r = amdgpu_discovery_set_display_ip_blocks(adev);
+ if (r)
+ return r;
+ }
+
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP)) {
r = amdgpu_discovery_set_smu_ip_blocks(adev);
if (r)
return r;
}
- r = amdgpu_discovery_set_display_ip_blocks(adev);
- if (r)
- return r;
+ if (likely(!dmi_check_system(imac5k_table))) {
+ r = amdgpu_discovery_set_display_ip_blocks(adev);
+ if (r)
+ return r;
+ }
r = amdgpu_discovery_set_gc_ip_blocks(adev);
if (r)
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 5b634ae07..a88c86051 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -639,6 +639,8 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
retrieve_dmi_info(&adev->dm);
if (adev->dm.edp0_on_dp1_quirk)
init_data.flags.support_edp0_on_dp1 = true;
+ if (adev->dm.imac5K_support)
+ init_data.flags.imac5K_support = true;
if (adev->dm.bb_from_dmub)
init_data.bb_from_dmub = adev->dm.bb_from_dmub;
@@ -1967,6 +1969,11 @@ static int dm_resume(struct amdgpu_ip_block *ip_block)
dc_exit_ips_for_hw_access(dm->dc);
WARN_ON(!dc_commit_streams(dm->dc, &commit_params));
+ if (dm->dc->config.imac5K_using_5K) {
+ const u8 value = 1;
+
+ core_link_write_dpcd(dm->dc->links[0], 0x4F1, &value, 1);
+ }
dm_gpureset_commit_state(dm->cached_dc_state, dm);
dm_gpureset_toggle_interrupts(adev, dm->cached_dc_state, true);
@@ -4739,6 +4746,25 @@ static void amdgpu_dm_commit_streams(struct drm_atomic_commit *state,
dc_exit_ips_for_hw_access(dm->dc);
WARN_ON(!dc_commit_streams(dm->dc, ¶ms));
+ if (dm->imac5K_support) {
+ for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
+ dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
+
+ if (!dm_new_crtc_state->stream)
+ continue;
+
+ if (dm_new_crtc_state->stream->signal != SIGNAL_TYPE_EDP)
+ continue;
+
+ if (new_crtc_state->mode.vdisplay == 2880 && new_crtc_state->mode.hdisplay == 2560) {
+ u8 value = 1;
+
+ core_link_write_dpcd(dm->dc->links[0], 0x4F1, &value, 1);
+ dm->dc->config.imac5K_using_5K = true;
+ } else
+ dm->dc->config.imac5K_using_5K = false;
+ }
+ }
bool frl_stream_found = false;
for (i = 0; i < params.stream_count; i++) {
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
index 1b91fe4c3..65a2330c6 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -698,6 +698,13 @@ struct amdgpu_display_manager {
*/
bool edp0_on_dp1_quirk;
+ /**
+ * @imac5K_support:
+ *
+ * quirk for iMac that support 5K
+ */
+ bool imac5K_support;
+
/**
* @dpia_aux_lock:
*
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
index 2b81396bd..2269b91c3 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
@@ -123,6 +123,13 @@ STATIC_IFN_KUNIT int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
drm_mode_vrefresh(adjusted_mode));
dm_new_connector_state->scaling = RMX_ASPECT;
}
+
+ if (aconnector->dc_link && aconnector->dc_link->dc->config.imac5K_support) {
+ if (crtc_state->mode.vdisplay != 2880)
+ dm_new_connector_state->scaling = RMX_FULL;
+ else
+ dm_new_connector_state->scaling = RMX_OFF;
+ }
return 0;
}
@@ -3130,9 +3137,19 @@ STATIC_IFN_KUNIT int amdgpu_dm_connector_get_modes(struct drm_connector *connect
const struct drm_edid *drm_edid = amdgpu_dm_connector->drm_edid;
struct dc_link_settings *verified_link_cap = &dc_link->verified_link_cap;
const struct dc *dc = dc_link->dc;
+ struct dc_sink *sink = amdgpu_dm_connector->dc_sink;
encoder = amdgpu_dm_connector_to_encoder(connector);
+ if (dc->config.imac5K_support && sink &&
+ sink->link->link_index == 1 && !connector->edid_blob_ptr) {
+ const struct drm_edid *kept = drm_edid_alloc(sink->dc_edid.raw_edid,
+ sink->dc_edid.length);
+
+ drm_edid_connector_update(connector, kept);
+ drm_edid_free(kept);
+ }
+
if (!drm_edid) {
amdgpu_dm_connector->num_modes =
drm_add_modes_noedid(connector, 640, 480);
@@ -3312,7 +3329,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
adev->mode_info.underscan_vborder_property,
0);
- if (!aconnector->mst_root)
+ if (!aconnector->mst_root && !(dm->imac5K_support && link_index <= 1))
drm_connector_attach_max_bpc_property(&aconnector->base, 8, 16);
aconnector->base.state->max_bpc = 16;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_quirks.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_quirks.c
index 259966703..8657dd972 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_quirks.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_quirks.c
@@ -33,11 +33,13 @@
struct amdgpu_dm_quirks {
bool aux_hpd_discon;
bool support_edp0_on_dp1;
+ bool imac5K_support;
};
static struct amdgpu_dm_quirks quirk_entries = {
.aux_hpd_discon = false,
- .support_edp0_on_dp1 = false
+ .support_edp0_on_dp1 = false,
+ .imac5K_support = false,
};
static int edp0_on_dp1_callback(const struct dmi_system_id *id)
@@ -52,6 +54,12 @@ static int aux_hpd_discon_callback(const struct dmi_system_id *id)
return 0;
}
+static int imac5K_support_callback(const struct dmi_system_id *id)
+{
+ quirk_entries.imac5K_support = true;
+ return 0;
+}
+
static const struct dmi_system_id dmi_quirk_table[] = {
{
.callback = aux_hpd_discon_callback,
@@ -151,6 +159,20 @@ static const struct dmi_system_id dmi_quirk_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "HP ProBook 465 16 inch G11 Notebook PC"),
},
},
+ {
+ .callback = imac5K_support_callback,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "iMac20,1"),
+ },
+ },
+ {
+ .callback = imac5K_support_callback,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "iMac20,2"),
+ },
+ },
{}
/* TODO: refactor this from a fixed table to a dynamic option */
};
@@ -162,6 +184,7 @@ void retrieve_dmi_info(struct amdgpu_display_manager *dm)
dm->aux_hpd_discon_quirk = false;
dm->edp0_on_dp1_quirk = false;
+ dm->imac5K_support = false;
dmi_id = dmi_check_system(dmi_quirk_table);
@@ -176,6 +199,10 @@ void retrieve_dmi_info(struct amdgpu_display_manager *dm)
dm->edp0_on_dp1_quirk = true;
drm_info(dev, "support_edp0_on_dp1 attached\n");
}
+ if (quirk_entries.imac5K_support) {
+ dm->imac5K_support = true;
+ drm_info(dev, "imac5K_support attached\n");
+ }
}
EXPORT_IF_KUNIT(retrieve_dmi_info);
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
index 187486d97..98f74ffc2 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -689,6 +689,14 @@ bool resource_are_streams_timing_synchronizable(
struct dc_stream_state *stream1,
struct dc_stream_state *stream2)
{
+
+ if (stream1->ctx->dc->config.imac5K_support &&
+ ((stream1->signal == SIGNAL_TYPE_EDP && stream2->signal == SIGNAL_TYPE_DISPLAY_PORT &&
+ stream2->link->link_index == 1) ||
+ (stream2->signal == SIGNAL_TYPE_EDP && stream1->signal == SIGNAL_TYPE_DISPLAY_PORT &&
+ stream1->link->link_index == 1)))
+ return true;
+
if (stream1->timing.h_total != stream2->timing.h_total)
return false;
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index d3c484f45..a0b746250 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -635,6 +635,8 @@ struct dc_config {
struct spl_sharpness_range dcn_sharpness_range;
struct spl_sharpness_range dcn_override_sharpness_range;
bool no_native422_support;
+ bool imac5K_support;
+ bool imac5K_using_5K;
};
enum visual_confirm {
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
index 7b3aa02dd..aba1dc9b4 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
@@ -2656,7 +2656,8 @@ enum dc_status dce110_apply_ctx_to_hw(
struct dce_hwseq *hws = dc->hwseq;
struct dc_bios *dcb = dc->ctx->dc_bios;
enum dc_status status;
- unsigned int i;
+ unsigned int i, n, enable_order[MAX_PIPES];
+ int primary = -1, companion = -1;
bool was_hpo_acquired = resource_is_hpo_acquired(dc->current_state);
bool is_hpo_acquired = resource_is_hpo_acquired(context);
@@ -2664,6 +2665,32 @@ enum dc_status dce110_apply_ctx_to_hw(
if (dc->config.use_pipe_ctx_sync_logic)
reset_syncd_pipes_from_disabled_pipes(dc, context);
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+
+ enable_order[i] = i;
+ if (!dc->config.imac5K_support || !pipe->stream ||
+ pipe->top_pipe || pipe->prev_odm_pipe)
+ continue;
+ if (pipe->stream->link->link_index == 0)
+ primary = i;
+ else if (pipe->stream->link->link_index == 1)
+ companion = i;
+ }
+ if (companion >= 0 && primary > companion) {
+ enable_order[companion] = primary;
+ enable_order[primary] = companion;
+ }
+
+ if (primary >= 0 && companion >= 0) {
+ struct pipe_ctx *old = &dc->current_state->res_ctx.pipe_ctx[primary];
+ struct dc_link *right = context->res_ctx.pipe_ctx[companion].stream->link;
+
+ if (!old->stream ||
+ pipe_need_reprogram(old, &context->res_ctx.pipe_ctx[primary]))
+ right->link_state_valid = false;
+ }
+
/* Reset old context */
/* look up the targets that have been removed since last commit */
hws->funcs.reset_hw_ctx_wrap(dc, context);
@@ -2705,10 +2732,12 @@ enum dc_status dce110_apply_ctx_to_hw(
dc->hwseq->funcs.setup_hpo_hw_control(dc->hwseq, is_hpo_acquired);
}
- for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ for (n = 0; n < dc->res_pool->pipe_count; n++) {
struct pipe_ctx *pipe_ctx_old =
- &dc->current_state->res_ctx.pipe_ctx[i];
- struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+ &dc->current_state->res_ctx.pipe_ctx[enable_order[n]];
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[enable_order[n]];
+
+ i = enable_order[n];
if (pipe_ctx->stream == NULL)
continue;
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_detection.c b/drivers/gpu/drm/amd/display/dc/link/link_detection.c
index b4546f93a..a92399753 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_detection.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.c
@@ -1205,7 +1205,10 @@ static bool detect_link_and_local_sink(struct dc_link *link,
if (!link->dpcd_caps.set_power_state_capable_edp)
link->wa_flags.dp_keep_receiver_powered = true;
}
-
+ if (dc->config.imac5K_support) {
+ const uint8_t val = 1;
+ core_link_write_dpcd(link, 0x4F1, &val, 1);
+ }
sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
sink_caps.signal = SIGNAL_TYPE_EDP;
break;
@@ -1634,6 +1637,15 @@ bool link_detect(struct dc_link *link, enum dc_detect_reason reason)
bool is_delegated_to_mst_top_mgr = false;
enum dc_connection_type pre_link_type = link->type;
+ if (link->local_sink &&
+ link->dc->config.imac5K_support &&
+ link->local_sink->link->link_index == 1)
+ return false;
+
+ if (reason == DETECT_REASON_BOOT && link->dc->config.imac5K_support &&
+ link->link_index == 1)
+ msleep(100);
+
is_local_sink_detect_success = detect_link_and_local_sink(link, reason);
if (is_local_sink_detect_success && link->local_sink) {
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
index 2aeb9a0e6..3d7d1ddc4 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
@@ -2084,6 +2084,9 @@ static enum dc_status enable_link_dp(struct dc_state *state,
!link->dc->config.enable_dpia_pre_training)
do_fallback = true;
+ if (link->dc->config.imac5K_support && link->link_index == 1)
+ msleep(100);
+
/*
* Temporary w/a to get DP2.0 link rates to work with SST.
* TODO DP2.0 - Workaround: Remove w/a if and when the issue is resolved.
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c
index 49521ac4b..e90164a58 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c
@@ -53,6 +53,11 @@ void dpcd_write_rx_power_ctrl(struct dc_link *link, bool on)
core_link_write_dpcd(link, DP_SET_POWER, &state,
sizeof(state));
+ if (on && link->dc->config.imac5K_support &&
+ link->connector_signal == SIGNAL_TYPE_EDP) {
+ state = 1;
+ core_link_write_dpcd(link, 0x4F1, &state, sizeof(state));
+ }
}
void dp_enable_link_phy(
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c
index 3be36d106..4eca11169 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c
@@ -1540,8 +1540,15 @@ static enum link_training_result dp_transition_to_video_idle(
*/
if (link->connector_signal != SIGNAL_TYPE_EDP && status == LINK_TRAINING_SUCCESS) {
msleep(5);
- if (!link->skip_fallback_on_link_loss)
+ if (link->dc->config.imac5K_support && link->link_index == 1) {
+ uint8_t lanes;
+
+ if (core_link_read_dpcd(link, DP_LANE0_1_STATUS,
+ &lanes, 1) != DC_OK)
+ status = LINK_TRAINING_LINK_LOSS;
+ } else if (!link->skip_fallback_on_link_loss) {
status = dp_check_link_loss_status(link, lt_settings);
+ }
}
return status;
}
--
2.55.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] drm/amd/amdgpu: Add 5K Support for iMac20,1 and iMac20,2
2026-11-04 19:36 [PATCH] drm/amd/amdgpu: Add 5K Support for iMac20,1 and iMac20,2 Atharva Tiwari
@ 2026-11-04 19:52 ` Alex Deucher
2026-11-04 20:02 ` Atharva Tiwari
2026-11-04 20:10 ` Atharva Tiwari
0 siblings, 2 replies; 4+ messages in thread
From: Alex Deucher @ 2026-11-04 19:52 UTC (permalink / raw)
To: Atharva Tiwari
Cc: Alex Deucher, Christian König, David Airlie, Simona Vetter,
Harry Wentland, Leo Li, Rodrigo Siqueira, amd-gfx, dri-devel,
linux-kernel
On Wed, Nov 4, 2026 at 2:46 PM Atharva Tiwari
<atharvatiwarilinuxdev@gmail.com> wrote:
>
> This code adds support for 5K in iMac20,1 and iMac20,2 with
> support of changing resolutions.
>
Please give a better description of what has changed here.
> Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4455
> Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4895
>
> Signed-off-by: Atharva Tiwari <atharvatiwarilinuxdev@gmail.com>
> ---
> drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 32 ++++++++++++++--
> .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 26 +++++++++++++
> .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 7 ++++
> .../display/amdgpu_dm/amdgpu_dm_connector.c | 19 +++++++++-
> .../amd/display/amdgpu_dm/amdgpu_dm_quirks.c | 29 ++++++++++++++-
> .../gpu/drm/amd/display/dc/core/dc_resource.c | 8 ++++
> drivers/gpu/drm/amd/display/dc/dc.h | 2 +
> .../amd/display/dc/hwss/dce110/dce110_hwseq.c | 37 +++++++++++++++++--
> .../drm/amd/display/dc/link/link_detection.c | 14 ++++++-
> .../gpu/drm/amd/display/dc/link/link_dpms.c | 3 ++
> .../display/dc/link/protocols/link_dp_phy.c | 5 +++
> .../dc/link/protocols/link_dp_training.c | 9 ++++-
> 12 files changed, 180 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
> index 890792a94..fc107e4fa 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
> @@ -21,6 +21,7 @@
> *
> */
>
> +#include <linux/dmi.h>
> #include <linux/firmware.h>
> #include <linux/kernfs.h>
>
> @@ -3412,6 +3413,22 @@ static int amdgpu_discovery_set_ualink_ip_blocks(struct amdgpu_device *adev)
> return 0;
> }
>
> +static const struct dmi_system_id imac5k_table[] = {
> + {
> + .matches = {
> + DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
> + DMI_MATCH(DMI_PRODUCT_NAME, "iMac20,1"),
> + },
> + },
> + {
> + .matches = {
> + DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
> + DMI_MATCH(DMI_PRODUCT_NAME, "iMac20,2"),
> + },
> + },
> + {}
> +};
> +
> int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
> {
> int r;
> @@ -4026,15 +4043,24 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
> }
> }
>
> + /* TODO: We should enable 5K in EFI and remove this quirk */
> + if (unlikely(dmi_check_system(imac5k_table))) {
> + r = amdgpu_discovery_set_display_ip_blocks(adev);
> + if (r)
> + return r;
> + }
What's the reason for this change?
> +
> if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP)) {
> r = amdgpu_discovery_set_smu_ip_blocks(adev);
> if (r)
> return r;
> }
>
> - r = amdgpu_discovery_set_display_ip_blocks(adev);
> - if (r)
> - return r;
> + if (likely(!dmi_check_system(imac5k_table))) {
> + r = amdgpu_discovery_set_display_ip_blocks(adev);
> + if (r)
> + return r;
> + }
>
> r = amdgpu_discovery_set_gc_ip_blocks(adev);
> if (r)
> 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 5b634ae07..a88c86051 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -639,6 +639,8 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
> retrieve_dmi_info(&adev->dm);
> if (adev->dm.edp0_on_dp1_quirk)
> init_data.flags.support_edp0_on_dp1 = true;
> + if (adev->dm.imac5K_support)
> + init_data.flags.imac5K_support = true;
>
> if (adev->dm.bb_from_dmub)
> init_data.bb_from_dmub = adev->dm.bb_from_dmub;
> @@ -1967,6 +1969,11 @@ static int dm_resume(struct amdgpu_ip_block *ip_block)
> dc_exit_ips_for_hw_access(dm->dc);
> WARN_ON(!dc_commit_streams(dm->dc, &commit_params));
>
> + if (dm->dc->config.imac5K_using_5K) {
> + const u8 value = 1;
> +
> + core_link_write_dpcd(dm->dc->links[0], 0x4F1, &value, 1);
> + }
> dm_gpureset_commit_state(dm->cached_dc_state, dm);
>
> dm_gpureset_toggle_interrupts(adev, dm->cached_dc_state, true);
> @@ -4739,6 +4746,25 @@ static void amdgpu_dm_commit_streams(struct drm_atomic_commit *state,
> dc_exit_ips_for_hw_access(dm->dc);
> WARN_ON(!dc_commit_streams(dm->dc, ¶ms));
>
> + if (dm->imac5K_support) {
> + for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
> + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
> +
> + if (!dm_new_crtc_state->stream)
> + continue;
> +
> + if (dm_new_crtc_state->stream->signal != SIGNAL_TYPE_EDP)
> + continue;
> +
> + if (new_crtc_state->mode.vdisplay == 2880 && new_crtc_state->mode.hdisplay == 2560) {
> + u8 value = 1;
> +
> + core_link_write_dpcd(dm->dc->links[0], 0x4F1, &value, 1);
> + dm->dc->config.imac5K_using_5K = true;
> + } else
> + dm->dc->config.imac5K_using_5K = false;
> + }
> + }
> bool frl_stream_found = false;
>
> for (i = 0; i < params.stream_count; i++) {
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> index 1b91fe4c3..65a2330c6 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> @@ -698,6 +698,13 @@ struct amdgpu_display_manager {
> */
> bool edp0_on_dp1_quirk;
>
> + /**
> + * @imac5K_support:
> + *
> + * quirk for iMac that support 5K
> + */
> + bool imac5K_support;
> +
> /**
> * @dpia_aux_lock:
> *
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
> index 2b81396bd..2269b91c3 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
> @@ -123,6 +123,13 @@ STATIC_IFN_KUNIT int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
> drm_mode_vrefresh(adjusted_mode));
> dm_new_connector_state->scaling = RMX_ASPECT;
> }
> +
> + if (aconnector->dc_link && aconnector->dc_link->dc->config.imac5K_support) {
> + if (crtc_state->mode.vdisplay != 2880)
> + dm_new_connector_state->scaling = RMX_FULL;
> + else
> + dm_new_connector_state->scaling = RMX_OFF;
> + }
> return 0;
> }
>
> @@ -3130,9 +3137,19 @@ STATIC_IFN_KUNIT int amdgpu_dm_connector_get_modes(struct drm_connector *connect
> const struct drm_edid *drm_edid = amdgpu_dm_connector->drm_edid;
> struct dc_link_settings *verified_link_cap = &dc_link->verified_link_cap;
> const struct dc *dc = dc_link->dc;
> + struct dc_sink *sink = amdgpu_dm_connector->dc_sink;
>
> encoder = amdgpu_dm_connector_to_encoder(connector);
>
> + if (dc->config.imac5K_support && sink &&
> + sink->link->link_index == 1 && !connector->edid_blob_ptr) {
> + const struct drm_edid *kept = drm_edid_alloc(sink->dc_edid.raw_edid,
> + sink->dc_edid.length);
> +
> + drm_edid_connector_update(connector, kept);
> + drm_edid_free(kept);
> + }
> +
> if (!drm_edid) {
> amdgpu_dm_connector->num_modes =
> drm_add_modes_noedid(connector, 640, 480);
> @@ -3312,7 +3329,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
> adev->mode_info.underscan_vborder_property,
> 0);
>
> - if (!aconnector->mst_root)
> + if (!aconnector->mst_root && !(dm->imac5K_support && link_index <= 1))
> drm_connector_attach_max_bpc_property(&aconnector->base, 8, 16);
>
> aconnector->base.state->max_bpc = 16;
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_quirks.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_quirks.c
> index 259966703..8657dd972 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_quirks.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_quirks.c
> @@ -33,11 +33,13 @@
> struct amdgpu_dm_quirks {
> bool aux_hpd_discon;
> bool support_edp0_on_dp1;
> + bool imac5K_support;
> };
>
> static struct amdgpu_dm_quirks quirk_entries = {
> .aux_hpd_discon = false,
> - .support_edp0_on_dp1 = false
> + .support_edp0_on_dp1 = false,
> + .imac5K_support = false,
> };
>
> static int edp0_on_dp1_callback(const struct dmi_system_id *id)
> @@ -52,6 +54,12 @@ static int aux_hpd_discon_callback(const struct dmi_system_id *id)
> return 0;
> }
>
> +static int imac5K_support_callback(const struct dmi_system_id *id)
> +{
> + quirk_entries.imac5K_support = true;
> + return 0;
> +}
> +
> static const struct dmi_system_id dmi_quirk_table[] = {
> {
> .callback = aux_hpd_discon_callback,
> @@ -151,6 +159,20 @@ static const struct dmi_system_id dmi_quirk_table[] = {
> DMI_MATCH(DMI_PRODUCT_NAME, "HP ProBook 465 16 inch G11 Notebook PC"),
> },
> },
> + {
> + .callback = imac5K_support_callback,
> + .matches = {
> + DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
> + DMI_MATCH(DMI_PRODUCT_NAME, "iMac20,1"),
> + },
> + },
> + {
> + .callback = imac5K_support_callback,
> + .matches = {
> + DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
> + DMI_MATCH(DMI_PRODUCT_NAME, "iMac20,2"),
> + },
> + },
> {}
> /* TODO: refactor this from a fixed table to a dynamic option */
> };
> @@ -162,6 +184,7 @@ void retrieve_dmi_info(struct amdgpu_display_manager *dm)
>
> dm->aux_hpd_discon_quirk = false;
> dm->edp0_on_dp1_quirk = false;
> + dm->imac5K_support = false;
>
> dmi_id = dmi_check_system(dmi_quirk_table);
>
> @@ -176,6 +199,10 @@ void retrieve_dmi_info(struct amdgpu_display_manager *dm)
> dm->edp0_on_dp1_quirk = true;
> drm_info(dev, "support_edp0_on_dp1 attached\n");
> }
> + if (quirk_entries.imac5K_support) {
> + dm->imac5K_support = true;
> + drm_info(dev, "imac5K_support attached\n");
> + }
> }
> EXPORT_IF_KUNIT(retrieve_dmi_info);
>
> diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
> index 187486d97..98f74ffc2 100644
> --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
> +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
> @@ -689,6 +689,14 @@ bool resource_are_streams_timing_synchronizable(
> struct dc_stream_state *stream1,
> struct dc_stream_state *stream2)
> {
> +
> + if (stream1->ctx->dc->config.imac5K_support &&
> + ((stream1->signal == SIGNAL_TYPE_EDP && stream2->signal == SIGNAL_TYPE_DISPLAY_PORT &&
> + stream2->link->link_index == 1) ||
> + (stream2->signal == SIGNAL_TYPE_EDP && stream1->signal == SIGNAL_TYPE_DISPLAY_PORT &&
> + stream1->link->link_index == 1)))
> + return true;
> +
> if (stream1->timing.h_total != stream2->timing.h_total)
> return false;
>
> diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
> index d3c484f45..a0b746250 100644
> --- a/drivers/gpu/drm/amd/display/dc/dc.h
> +++ b/drivers/gpu/drm/amd/display/dc/dc.h
> @@ -635,6 +635,8 @@ struct dc_config {
> struct spl_sharpness_range dcn_sharpness_range;
> struct spl_sharpness_range dcn_override_sharpness_range;
> bool no_native422_support;
> + bool imac5K_support;
> + bool imac5K_using_5K;
> };
>
> enum visual_confirm {
> diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
> index 7b3aa02dd..aba1dc9b4 100644
> --- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
> +++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
> @@ -2656,7 +2656,8 @@ enum dc_status dce110_apply_ctx_to_hw(
> struct dce_hwseq *hws = dc->hwseq;
> struct dc_bios *dcb = dc->ctx->dc_bios;
> enum dc_status status;
> - unsigned int i;
> + unsigned int i, n, enable_order[MAX_PIPES];
> + int primary = -1, companion = -1;
> bool was_hpo_acquired = resource_is_hpo_acquired(dc->current_state);
> bool is_hpo_acquired = resource_is_hpo_acquired(context);
>
> @@ -2664,6 +2665,32 @@ enum dc_status dce110_apply_ctx_to_hw(
> if (dc->config.use_pipe_ctx_sync_logic)
> reset_syncd_pipes_from_disabled_pipes(dc, context);
>
> + for (i = 0; i < dc->res_pool->pipe_count; i++) {
> + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
> +
> + enable_order[i] = i;
> + if (!dc->config.imac5K_support || !pipe->stream ||
> + pipe->top_pipe || pipe->prev_odm_pipe)
> + continue;
> + if (pipe->stream->link->link_index == 0)
> + primary = i;
> + else if (pipe->stream->link->link_index == 1)
> + companion = i;
> + }
> + if (companion >= 0 && primary > companion) {
> + enable_order[companion] = primary;
> + enable_order[primary] = companion;
> + }
> +
> + if (primary >= 0 && companion >= 0) {
> + struct pipe_ctx *old = &dc->current_state->res_ctx.pipe_ctx[primary];
> + struct dc_link *right = context->res_ctx.pipe_ctx[companion].stream->link;
> +
> + if (!old->stream ||
> + pipe_need_reprogram(old, &context->res_ctx.pipe_ctx[primary]))
> + right->link_state_valid = false;
> + }
> +
> /* Reset old context */
> /* look up the targets that have been removed since last commit */
> hws->funcs.reset_hw_ctx_wrap(dc, context);
> @@ -2705,10 +2732,12 @@ enum dc_status dce110_apply_ctx_to_hw(
> dc->hwseq->funcs.setup_hpo_hw_control(dc->hwseq, is_hpo_acquired);
> }
>
> - for (i = 0; i < dc->res_pool->pipe_count; i++) {
> + for (n = 0; n < dc->res_pool->pipe_count; n++) {
> struct pipe_ctx *pipe_ctx_old =
> - &dc->current_state->res_ctx.pipe_ctx[i];
> - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
> + &dc->current_state->res_ctx.pipe_ctx[enable_order[n]];
> + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[enable_order[n]];
> +
> + i = enable_order[n];
>
> if (pipe_ctx->stream == NULL)
> continue;
> diff --git a/drivers/gpu/drm/amd/display/dc/link/link_detection.c b/drivers/gpu/drm/amd/display/dc/link/link_detection.c
> index b4546f93a..a92399753 100644
> --- a/drivers/gpu/drm/amd/display/dc/link/link_detection.c
> +++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.c
> @@ -1205,7 +1205,10 @@ static bool detect_link_and_local_sink(struct dc_link *link,
> if (!link->dpcd_caps.set_power_state_capable_edp)
> link->wa_flags.dp_keep_receiver_powered = true;
> }
> -
> + if (dc->config.imac5K_support) {
> + const uint8_t val = 1;
> + core_link_write_dpcd(link, 0x4F1, &val, 1);
> + }
> sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
> sink_caps.signal = SIGNAL_TYPE_EDP;
> break;
> @@ -1634,6 +1637,15 @@ bool link_detect(struct dc_link *link, enum dc_detect_reason reason)
> bool is_delegated_to_mst_top_mgr = false;
> enum dc_connection_type pre_link_type = link->type;
>
> + if (link->local_sink &&
> + link->dc->config.imac5K_support &&
> + link->local_sink->link->link_index == 1)
> + return false;
> +
> + if (reason == DETECT_REASON_BOOT && link->dc->config.imac5K_support &&
> + link->link_index == 1)
> + msleep(100);
> +
> is_local_sink_detect_success = detect_link_and_local_sink(link, reason);
>
> if (is_local_sink_detect_success && link->local_sink) {
> diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
> index 2aeb9a0e6..3d7d1ddc4 100644
> --- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
> +++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
> @@ -2084,6 +2084,9 @@ static enum dc_status enable_link_dp(struct dc_state *state,
> !link->dc->config.enable_dpia_pre_training)
> do_fallback = true;
>
> + if (link->dc->config.imac5K_support && link->link_index == 1)
> + msleep(100);
> +
> /*
> * Temporary w/a to get DP2.0 link rates to work with SST.
> * TODO DP2.0 - Workaround: Remove w/a if and when the issue is resolved.
> diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c
> index 49521ac4b..e90164a58 100644
> --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c
> +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c
> @@ -53,6 +53,11 @@ void dpcd_write_rx_power_ctrl(struct dc_link *link, bool on)
> core_link_write_dpcd(link, DP_SET_POWER, &state,
> sizeof(state));
>
> + if (on && link->dc->config.imac5K_support &&
> + link->connector_signal == SIGNAL_TYPE_EDP) {
> + state = 1;
> + core_link_write_dpcd(link, 0x4F1, &state, sizeof(state));
> + }
> }
>
> void dp_enable_link_phy(
> diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c
> index 3be36d106..4eca11169 100644
> --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c
> +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c
> @@ -1540,8 +1540,15 @@ static enum link_training_result dp_transition_to_video_idle(
> */
> if (link->connector_signal != SIGNAL_TYPE_EDP && status == LINK_TRAINING_SUCCESS) {
> msleep(5);
> - if (!link->skip_fallback_on_link_loss)
> + if (link->dc->config.imac5K_support && link->link_index == 1) {
> + uint8_t lanes;
> +
> + if (core_link_read_dpcd(link, DP_LANE0_1_STATUS,
> + &lanes, 1) != DC_OK)
> + status = LINK_TRAINING_LINK_LOSS;
> + } else if (!link->skip_fallback_on_link_loss) {
> status = dp_check_link_loss_status(link, lt_settings);
> + }
> }
> return status;
> }
I think the rest of this can be simplified quite a bit. I'd suggest
rebasing this on the other 5K support patches and see how much of that
code you can share.
https://lists.freedesktop.org/archives/dri-devel/2026-November/610011.html
Alex
> --
> 2.55.0
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] drm/amd/amdgpu: Add 5K Support for iMac20,1 and iMac20,2
2026-11-04 19:52 ` Alex Deucher
@ 2026-11-04 20:02 ` Atharva Tiwari
2026-11-04 20:10 ` Atharva Tiwari
1 sibling, 0 replies; 4+ messages in thread
From: Atharva Tiwari @ 2026-11-04 20:02 UTC (permalink / raw)
To: alexdeucher
Cc: airlied, alexander.deucher, amd-gfx, atharvatiwarilinuxdev,
christian.koenig, dri-devel, harry.wentland, linux-kernel,
simona, siqueira, sunpeng.li
> What's the reason for this change?
This is the code that fixes the SMU boot issue, that we discussed eariler:
https://lore.kernel.org/all/20261103160553.1431-1-atharvatiwarilinuxdev@gmail.com/
Its confirmed to be 0x4F1 as OCLP enables it, and with OCLP and no patches it booted fine.
I plan to add 5K support to efi libstub or something in the future, hence the TODO, so we
get 5K in simpledrm and get rid of this not good looking quirk.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] drm/amd/amdgpu: Add 5K Support for iMac20,1 and iMac20,2
2026-11-04 19:52 ` Alex Deucher
2026-11-04 20:02 ` Atharva Tiwari
@ 2026-11-04 20:10 ` Atharva Tiwari
1 sibling, 0 replies; 4+ messages in thread
From: Atharva Tiwari @ 2026-11-04 20:10 UTC (permalink / raw)
To: alexdeucher
Cc: airlied, alexander.deucher, amd-gfx, atharvatiwarilinuxdev,
christian.koenig, dri-devel, harry.wentland, linux-kernel,
simona, siqueira, sunpeng.li
> I think the rest of this can be simplified quite a bit. I'd suggest
> rebasing this on the other 5K support patches and see how much of that
> code you can share.
> https://lists.freedesktop.org/archives/dri-devel/2026-November/610011.html
The code that i saw, dosent have the ability to change resolutions, and the code
it self, is basically completely different, for example writing 0 to 0x4F1 completely
kills 5K forever, you cant alive it again on iMac20,1 and the code does that.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-11-04 20:11 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-04 19:36 [PATCH] drm/amd/amdgpu: Add 5K Support for iMac20,1 and iMac20,2 Atharva Tiwari
2026-11-04 19:52 ` Alex Deucher
2026-11-04 20:02 ` Atharva Tiwari
2026-11-04 20:10 ` Atharva Tiwari
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®