Skip to content

Commit a23360c

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 185f253 commit a23360c

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
@@ -1822,6 +1822,7 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
18221822
struct drm_connector *connector = &vc4_hdmi->connector;
18231823
struct drm_connector_state *old_conn_state = drm_atomic_get_old_connector_state(conn_state->state, connector);
18241824
struct vc4_hdmi_connector_state *old_vc4_state = conn_state_to_vc4_hdmi_conn_state(old_conn_state);
1825+
struct vc4_dev *vc4 = to_vc4_dev(connector->dev);
18251826
unsigned long long pixel_rate = mode->clock * 1000;
18261827
unsigned long long tmds_rate;
18271828
int ret;
@@ -1846,6 +1847,12 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
18461847
return -EINVAL;
18471848
}
18481849

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

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

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

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)