Skip to content

Commit d0f6f32

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 65f69aa commit d0f6f32

File tree

3 files changed

+25
-0
lines changed

3 files changed

+25
-0
lines changed

drivers/gpu/drm/vc4/vc4_drv.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,12 @@ struct vc4_hvs {
351351
* available.
352352
*/
353353
bool vc5_hdmi_enable_scrambling;
354+
355+
/*
356+
* 4096x2160@60 requires a core overclock to work, so register
357+
* whether that is sufficient.
358+
*/
359+
bool vc5_hdmi_enable_4096by2160;
354360
};
355361

356362
struct vc4_plane {

drivers/gpu/drm/vc4/vc4_hdmi.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1821,6 +1821,7 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
18211821
struct drm_connector *connector = &vc4_hdmi->connector;
18221822
struct drm_connector_state *old_conn_state = drm_atomic_get_old_connector_state(conn_state->state, connector);
18231823
struct vc4_hdmi_connector_state *old_vc4_state = conn_state_to_vc4_hdmi_conn_state(old_conn_state);
1824+
struct vc4_dev *vc4 = to_vc4_dev(connector->dev);
18241825
unsigned long long pixel_rate = mode->clock * 1000;
18251826
unsigned long long tmds_rate;
18261827
int ret;
@@ -1845,6 +1846,12 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
18451846
return -EINVAL;
18461847
}
18471848

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

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

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

drivers/gpu/drm/vc4/vc4_hvs.c

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

899899
if (vc4->is_vc5) {
900+
unsigned long min_rate;
900901
unsigned long max_rate;
901902

902903
hvs->core_clk = devm_clk_get(&pdev->dev, NULL);
@@ -909,6 +910,10 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
909910
if (max_rate >= 550000000)
910911
hvs->vc5_hdmi_enable_scrambling = true;
911912

913+
min_rate = clk_get_min_rate(hvs->core_clk);
914+
if (min_rate >= 600000000)
915+
hvs->vc5_hdmi_enable_4096by2160 = true;
916+
912917
ret = clk_prepare_enable(hvs->core_clk);
913918
if (ret) {
914919
dev_err(&pdev->dev, "Couldn't enable the core clock\n");

0 commit comments

Comments
 (0)