Skip to content

Commit

Permalink
kms/vc4_hdmi: Refuse 4096x2160@60 hdmi modes
Browse files Browse the repository at this point in the history
These are no reliable without overclocking.
See: #5034

Signed-off-by: Dom Cobley <popcornmix@gmail.com>
  • Loading branch information
popcornmix committed Nov 18, 2022
1 parent 636a9d1 commit 43ecb4d
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 0 deletions.
6 changes: 6 additions & 0 deletions drivers/gpu/drm/vc4/vc4_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,12 @@ struct vc4_hvs {
struct drm_mm_node mitchell_netravali_filter;

struct debugfs_regset32 regset;

/*
* 4096x2160@60 requires a core overclock to work, so register
* whether that is sufficient.
*/
bool vc5_hdmi_enable_4096by2160;
};

struct vc4_plane {
Expand Down
14 changes: 14 additions & 0 deletions drivers/gpu/drm/vc4/vc4_hdmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1812,6 +1812,7 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
struct vc4_dev *vc4 = to_vc4_dev(encoder->dev);
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
struct drm_connector *connector = &vc4_hdmi->connector;
struct drm_connector_state *old_conn_state =
Expand Down Expand Up @@ -1844,6 +1845,12 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
return -EINVAL;
}

/* 4096x2160@60 is not reliable without overclocking core */
if (mode->hdisplay > 3840 && mode->vdisplay >= 2160 &&
drm_mode_vrefresh(mode) >= 50 &&
!vc4->hvs->vc5_hdmi_enable_4096by2160)
return -EINVAL;

/*
* The 1440p@60 pixel rate is in the same range than the first
* WiFi channel (between 2.4GHz and 2.422GHz with 22MHz
Expand Down Expand Up @@ -1875,13 +1882,20 @@ vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
const struct drm_display_mode *mode)
{
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
const struct drm_connector *connector = &vc4_hdmi->connector;
struct vc4_dev *vc4 = to_vc4_dev(connector->dev);

if (vc4_hdmi->variant->unsupported_odd_h_timings &&
!(mode->flags & DRM_MODE_FLAG_DBLCLK) &&
((mode->hdisplay % 2) || (mode->hsync_start % 2) ||
(mode->hsync_end % 2) || (mode->htotal % 2)))
return MODE_H_ILLEGAL;

if (mode->hdisplay > 3840 && mode->vdisplay >= 2160 &&
drm_mode_vrefresh(mode) >= 50 &&
!vc4->hvs->vc5_hdmi_enable_4096by2160)
return MODE_CLOCK_HIGH;

return vc4_hdmi_encoder_clock_valid(vc4_hdmi, mode->clock * 1000);
}

Expand Down
6 changes: 6 additions & 0 deletions drivers/gpu/drm/vc4/vc4_hvs.c
Original file line number Diff line number Diff line change
Expand Up @@ -898,12 +898,18 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
hvs->regset.nregs = ARRAY_SIZE(hvs_regs);

if (vc4->is_vc5) {
unsigned long min_rate;

hvs->core_clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(hvs->core_clk)) {
dev_err(&pdev->dev, "Couldn't get core clock\n");
return PTR_ERR(hvs->core_clk);
}

min_rate = rpi_firmware_clk_get_min_rate(hvs->core_clk);
if (min_rate >= 600000000)
hvs->vc5_hdmi_enable_4096by2160 = true;

ret = clk_prepare_enable(hvs->core_clk);
if (ret) {
dev_err(&pdev->dev, "Couldn't enable the core clock\n");
Expand Down

0 comments on commit 43ecb4d

Please sign in to comment.