Skip to content

Commit 43ecb4d

Browse files
committed
kms/vc4_hdmi: Refuse 4096x2160@60 hdmi modes
These are no reliable without overclocking. See: #5034 Signed-off-by: Dom Cobley <[email protected]>
1 parent 636a9d1 commit 43ecb4d

File tree

3 files changed

+26
-0
lines changed

3 files changed

+26
-0
lines changed

drivers/gpu/drm/vc4/vc4_drv.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,12 @@ struct vc4_hvs {
345345
struct drm_mm_node mitchell_netravali_filter;
346346

347347
struct debugfs_regset32 regset;
348+
349+
/*
350+
* 4096x2160@60 requires a core overclock to work, so register
351+
* whether that is sufficient.
352+
*/
353+
bool vc5_hdmi_enable_4096by2160;
348354
};
349355

350356
struct vc4_plane {

drivers/gpu/drm/vc4/vc4_hdmi.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1812,6 +1812,7 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
18121812
struct drm_crtc_state *crtc_state,
18131813
struct drm_connector_state *conn_state)
18141814
{
1815+
struct vc4_dev *vc4 = to_vc4_dev(encoder->dev);
18151816
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
18161817
struct drm_connector *connector = &vc4_hdmi->connector;
18171818
struct drm_connector_state *old_conn_state =
@@ -1844,6 +1845,12 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
18441845
return -EINVAL;
18451846
}
18461847

1848+
/* 4096x2160@60 is not reliable without overclocking core */
1849+
if (mode->hdisplay > 3840 && mode->vdisplay >= 2160 &&
1850+
drm_mode_vrefresh(mode) >= 50 &&
1851+
!vc4->hvs->vc5_hdmi_enable_4096by2160)
1852+
return -EINVAL;
1853+
18471854
/*
18481855
* The 1440p@60 pixel rate is in the same range than the first
18491856
* WiFi channel (between 2.4GHz and 2.422GHz with 22MHz
@@ -1875,13 +1882,20 @@ vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
18751882
const struct drm_display_mode *mode)
18761883
{
18771884
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
1885+
const struct drm_connector *connector = &vc4_hdmi->connector;
1886+
struct vc4_dev *vc4 = to_vc4_dev(connector->dev);
18781887

18791888
if (vc4_hdmi->variant->unsupported_odd_h_timings &&
18801889
!(mode->flags & DRM_MODE_FLAG_DBLCLK) &&
18811890
((mode->hdisplay % 2) || (mode->hsync_start % 2) ||
18821891
(mode->hsync_end % 2) || (mode->htotal % 2)))
18831892
return MODE_H_ILLEGAL;
18841893

1894+
if (mode->hdisplay > 3840 && mode->vdisplay >= 2160 &&
1895+
drm_mode_vrefresh(mode) >= 50 &&
1896+
!vc4->hvs->vc5_hdmi_enable_4096by2160)
1897+
return MODE_CLOCK_HIGH;
1898+
18851899
return vc4_hdmi_encoder_clock_valid(vc4_hdmi, mode->clock * 1000);
18861900
}
18871901

drivers/gpu/drm/vc4/vc4_hvs.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -898,12 +898,18 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
898898
hvs->regset.nregs = ARRAY_SIZE(hvs_regs);
899899

900900
if (vc4->is_vc5) {
901+
unsigned long min_rate;
902+
901903
hvs->core_clk = devm_clk_get(&pdev->dev, NULL);
902904
if (IS_ERR(hvs->core_clk)) {
903905
dev_err(&pdev->dev, "Couldn't get core clock\n");
904906
return PTR_ERR(hvs->core_clk);
905907
}
906908

909+
min_rate = rpi_firmware_clk_get_min_rate(hvs->core_clk);
910+
if (min_rate >= 600000000)
911+
hvs->vc5_hdmi_enable_4096by2160 = true;
912+
907913
ret = clk_prepare_enable(hvs->core_clk);
908914
if (ret) {
909915
dev_err(&pdev->dev, "Couldn't enable the core clock\n");

0 commit comments

Comments
 (0)