On Wed, Nov 4, 2026 at 2:46 PM Atharva Tiwari
<[email protected]> 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 <[email protected]>
> ---
>  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, &params));
>
> +       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
>

Reply via email to