Re: [PATCH v3 1/2] drm/radeon: fix internal display on iMac11, 1 (RV770/DCE3.1)

2026-05-19 Thread Alex Deucher
On Tue, May 19, 2026 at 3:19 AM Gilles Risch  wrote:
>
> The Apple iMac11,1 (late 2009) has an integrated ATI Mobility Radeon
> HD 4850 (RV770/M98L) with a 2560x1440 internal panel connected via an
> internal DisplayPort path. This machine suffers from a similar problem
> as the iMac10,1 (late 2009) and the iMac11,2 (mid 2010). Without this
> fix the display stays dark under KMS. Two issues are addressed:
>
> 1. The RV770 implements DCE3.1 and not DCE3.2. ASIC_IS_DCE32() starts at
>CHIP_RV730 which is newer than RV770, so the RV770 never matched the
>DCE3.2 PLL and encoder logic. Introduce ASIC_IS_DCE31() starting at
>CHIP_RV770 to fix this.
>
> 2. Apple routed the internal display through Link B of the DIG encoder
>instead of Link A, as observed in the kernel display connector log.
>The same quirk already exists for iMac10,1 and iMac11,2 - iMac11,1
>was simply missing from the list.
>
> Note: resume from suspend still results in a dark screen as the DP
> re-driver chips on the mainboard lose their state during power-off.
> This will be addressed in a follow-up patch.
>
> Fixes freedesktop issue 164
> Link: https://gitlab.freedesktop.org/xorg/driver/xf86-video-ati/-/issues/164
>
> Signed-off-by: Gilles Risch 
> ---
> v3: No code changes.
>
>  drivers/gpu/drm/radeon/atombios_crtc.c | 4 ++--
>  drivers/gpu/drm/radeon/atombios_encoders.c | 9 +
>  drivers/gpu/drm/radeon/radeon.h| 1 +
>  3 files changed, 8 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c 
> b/drivers/gpu/drm/radeon/atombios_crtc.c
> index 2fc0334e0d6c..3c6d332739e3 100644
> --- a/drivers/gpu/drm/radeon/atombios_crtc.c
> +++ b/drivers/gpu/drm/radeon/atombios_crtc.c
> @@ -580,7 +580,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
> radeon_crtc->pll_flags |= 
> (/*RADEON_PLL_USE_FRAC_FB_DIV |*/
> RADEON_PLL_PREFER_CLOSEST_LOWER);
>
> -   if (ASIC_IS_DCE32(rdev) && mode->clock > 20)/* 
> range limits??? */
> +   if (ASIC_IS_DCE31(rdev) && mode->clock > 20)/* 
> range limits??? */
> radeon_crtc->pll_flags |= 
> RADEON_PLL_PREFER_HIGH_FB_DIV;
> else
> radeon_crtc->pll_flags |= 
> RADEON_PLL_PREFER_LOW_REF_DIV;
> @@ -594,7 +594,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
> if (((rdev->family == CHIP_RS780) || (rdev->family == 
> CHIP_RS880))
> && !radeon_crtc->ss_enabled)
> radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV;
> -   if (ASIC_IS_DCE32(rdev) && mode->clock > 165000)
> +   if (ASIC_IS_DCE31(rdev) && mode->clock > 165000)

Can you switch these to dmi matches as well?  This change will also
change the behavior for other boards with respect to the PLL
calculations which are often pretty sensitive and may cause
regressions.

Alex

> radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV;
> } else {
> radeon_crtc->pll_flags |= RADEON_PLL_LEGACY;
> diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c 
> b/drivers/gpu/drm/radeon/atombios_encoders.c
> index 5cfd8fcfa5e8..4e984973c043 100644
> --- a/drivers/gpu/drm/radeon/atombios_encoders.c
> +++ b/drivers/gpu/drm/radeon/atombios_encoders.c
> @@ -2123,12 +2123,13 @@ int radeon_atom_pick_dig_encoder(struct drm_encoder 
> *encoder, int fe_idx)
> }
>
> /*
> -* On DCE32 any encoder can drive any block so usually just use crtc 
> id,
> -* but Apple thinks different at least on iMac10,1 and iMac11,2, so 
> there use linkb,
> -* otherwise the internal eDP panel will stay dark.
> +* On DCE31 and DCE32 any encoder can drive any block so usually just 
> use crtc id,
> +* but Apple thinks different at least on iMac10,1, iMac11,1 and 
> iMac11,2,
> +* so there use linkb, otherwise the internal eDP panel will stay 
> dark.
>  */
> -   if (ASIC_IS_DCE32(rdev)) {
> +   if (ASIC_IS_DCE31(rdev)) {
> if (dmi_match(DMI_PRODUCT_NAME, "iMac10,1") ||
> +   dmi_match(DMI_PRODUCT_NAME, "iMac11,1") ||
> dmi_match(DMI_PRODUCT_NAME, "iMac11,2"))
> enc_idx = (dig->linkb) ? 1 : 0;
> else
> diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
> index 527b9d19d730..6b7c0abe49fb 100644
> --- a/drivers/gpu/drm/radeon/radeon.h
> +++ b/drivers/gpu/drm/radeon/radeon.h
> @@ -2625,6 +2625,7 @@ void r100_pll_errata_after_index(struct radeon_device 
> *rdev);
> (rdev->family == CHIP_RS740)  ||\
> (rdev->family >= CHIP_R600))
>  #define ASIC_IS_DCE3(rdev) ((rdev->family >= CHIP_RV620))
> +#define ASIC_IS_DCE31(rdev) ((rdev->family >= CHIP_RV770))
>  #define ASIC_IS_DCE32(rdev) (

[PATCH v3 1/2] drm/radeon: fix internal display on iMac11, 1 (RV770/DCE3.1)

2026-05-19 Thread Gilles Risch
The Apple iMac11,1 (late 2009) has an integrated ATI Mobility Radeon
HD 4850 (RV770/M98L) with a 2560x1440 internal panel connected via an
internal DisplayPort path. This machine suffers from a similar problem
as the iMac10,1 (late 2009) and the iMac11,2 (mid 2010). Without this
fix the display stays dark under KMS. Two issues are addressed:

1. The RV770 implements DCE3.1 and not DCE3.2. ASIC_IS_DCE32() starts at
   CHIP_RV730 which is newer than RV770, so the RV770 never matched the
   DCE3.2 PLL and encoder logic. Introduce ASIC_IS_DCE31() starting at
   CHIP_RV770 to fix this.

2. Apple routed the internal display through Link B of the DIG encoder
   instead of Link A, as observed in the kernel display connector log.
   The same quirk already exists for iMac10,1 and iMac11,2 - iMac11,1
   was simply missing from the list.

Note: resume from suspend still results in a dark screen as the DP
re-driver chips on the mainboard lose their state during power-off.
This will be addressed in a follow-up patch.

Fixes freedesktop issue 164
Link: https://gitlab.freedesktop.org/xorg/driver/xf86-video-ati/-/issues/164

Signed-off-by: Gilles Risch 
---
v3: No code changes. 

 drivers/gpu/drm/radeon/atombios_crtc.c | 4 ++--
 drivers/gpu/drm/radeon/atombios_encoders.c | 9 +
 drivers/gpu/drm/radeon/radeon.h| 1 +
 3 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c 
b/drivers/gpu/drm/radeon/atombios_crtc.c
index 2fc0334e0d6c..3c6d332739e3 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -580,7 +580,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
radeon_crtc->pll_flags |= (/*RADEON_PLL_USE_FRAC_FB_DIV 
|*/
RADEON_PLL_PREFER_CLOSEST_LOWER);
 
-   if (ASIC_IS_DCE32(rdev) && mode->clock > 20)/* 
range limits??? */
+   if (ASIC_IS_DCE31(rdev) && mode->clock > 20)/* 
range limits??? */
radeon_crtc->pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
else
radeon_crtc->pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
@@ -594,7 +594,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
if (((rdev->family == CHIP_RS780) || (rdev->family == 
CHIP_RS880))
&& !radeon_crtc->ss_enabled)
radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV;
-   if (ASIC_IS_DCE32(rdev) && mode->clock > 165000)
+   if (ASIC_IS_DCE31(rdev) && mode->clock > 165000)
radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV;
} else {
radeon_crtc->pll_flags |= RADEON_PLL_LEGACY;
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c 
b/drivers/gpu/drm/radeon/atombios_encoders.c
index 5cfd8fcfa5e8..4e984973c043 100644
--- a/drivers/gpu/drm/radeon/atombios_encoders.c
+++ b/drivers/gpu/drm/radeon/atombios_encoders.c
@@ -2123,12 +2123,13 @@ int radeon_atom_pick_dig_encoder(struct drm_encoder 
*encoder, int fe_idx)
}
 
/*
-* On DCE32 any encoder can drive any block so usually just use crtc id,
-* but Apple thinks different at least on iMac10,1 and iMac11,2, so 
there use linkb,
-* otherwise the internal eDP panel will stay dark.
+* On DCE31 and DCE32 any encoder can drive any block so usually just 
use crtc id,
+* but Apple thinks different at least on iMac10,1, iMac11,1 and 
iMac11,2,
+* so there use linkb, otherwise the internal eDP panel will stay dark.
 */
-   if (ASIC_IS_DCE32(rdev)) {
+   if (ASIC_IS_DCE31(rdev)) {
if (dmi_match(DMI_PRODUCT_NAME, "iMac10,1") ||
+   dmi_match(DMI_PRODUCT_NAME, "iMac11,1") ||
dmi_match(DMI_PRODUCT_NAME, "iMac11,2"))
enc_idx = (dig->linkb) ? 1 : 0;
else
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 527b9d19d730..6b7c0abe49fb 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -2625,6 +2625,7 @@ void r100_pll_errata_after_index(struct radeon_device 
*rdev);
(rdev->family == CHIP_RS740)  ||\
(rdev->family >= CHIP_R600))
 #define ASIC_IS_DCE3(rdev) ((rdev->family >= CHIP_RV620))
+#define ASIC_IS_DCE31(rdev) ((rdev->family >= CHIP_RV770))
 #define ASIC_IS_DCE32(rdev) ((rdev->family >= CHIP_RV730))
 #define ASIC_IS_DCE4(rdev) ((rdev->family >= CHIP_CEDAR))
 #define ASIC_IS_DCE41(rdev) ((rdev->family >= CHIP_PALM) && \
-- 
2.47.3